data.isa revision 7224
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                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
169                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
170                return new Rev(machInst, rd, rm);
171            } else if (op2 == 0x3) {
172                if (a == 0xf) {
173                    return new WarnUnimplemented("sxth", machInst);
174                } else {
175                    return new WarnUnimplemented("sxtah", machInst);
176                }
177            } else if (op2 == 0x5) {
178                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
179                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
180                return new Rev16(machInst, rd, rm);
181            }
182            break;
183          case 0x4:
184            if (op2 == 0x3) {
185                if (a == 0xf) {
186                    return new WarnUnimplemented("uxtb16", machInst);
187                } else {
188                    return new WarnUnimplemented("uxtab16", machInst);
189                }
190            }
191            break;
192          case 0x6:
193            if (op2 == 0x1) {
194                return new WarnUnimplemented("usat16", machInst);
195            } else if (op2 == 0x3) {
196                if (a == 0xf) {
197                    return new WarnUnimplemented("uxtb", machInst);
198                } else {
199                    return new WarnUnimplemented("uxtab", machInst);
200                }
201            }
202            break;
203          case 0x7:
204            if (op2 == 0x1) {
205                return new WarnUnimplemented("rbit", machInst);
206            } else if (op2 == 0x3) {
207                if (a == 0xf) {
208                    return new WarnUnimplemented("uxth", machInst);
209                } else {
210                    return new WarnUnimplemented("uxtah", machInst);
211                }
212            } else if (op2 == 0x5) {
213                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
214                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
215                return new Revsh(machInst, rd, rm);
216            }
217            break;
218        }
219        return new Unknown(machInst);
220    }
221    '''
222}};
223
224def format ArmParallelAddSubtract() {{
225    decode_block='''
226    {
227        const uint32_t op1 = bits(machInst, 21, 20);
228        const uint32_t op2 = bits(machInst, 7, 5);
229        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
230        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
231        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
232        if (bits(machInst, 22) == 0) {
233            switch (op1) {
234              case 0x1:
235                switch (op2) {
236                  case 0x0:
237                    return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL);
238                  case 0x1:
239                    return new SasxRegCc(machInst, rd, rn, rm, 0, LSL);
240                  case 0x2:
241                    return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL);
242                  case 0x3:
243                    return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL);
244                  case 0x4:
245                    return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL);
246                  case 0x7:
247                    return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL);
248                }
249                break;
250              case 0x2:
251                switch (op2) {
252                  case 0x0:
253                    return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
254                  case 0x1:
255                    return new QasxReg(machInst, rd, rn, rm, 0, LSL);
256                  case 0x2:
257                    return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
258                  case 0x3:
259                    return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
260                  case 0x4:
261                    return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
262                  case 0x7:
263                    return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
264                }
265                break;
266              case 0x3:
267                switch (op2) {
268                  case 0x0:
269                    return new WarnUnimplemented("shadd16", machInst);
270                  case 0x1:
271                    return new WarnUnimplemented("shasx", machInst);
272                  case 0x2:
273                    return new WarnUnimplemented("shsax", machInst);
274                  case 0x3:
275                    return new WarnUnimplemented("shsub16", machInst);
276                  case 0x4:
277                    return new WarnUnimplemented("shadd8", machInst);
278                  case 0x7:
279                    return new WarnUnimplemented("shsub8", machInst);
280                }
281                break;
282            }
283        } else {
284            switch (op1) {
285              case 0x1:
286                switch (op2) {
287                  case 0x0:
288                    return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL);
289                  case 0x1:
290                    return new UasxRegCc(machInst, rd, rn, rm, 0, LSL);
291                  case 0x2:
292                    return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL);
293                  case 0x3:
294                    return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL);
295                  case 0x4:
296                    return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL);
297                  case 0x7:
298                    return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL);
299                }
300                break;
301              case 0x2:
302                switch (op2) {
303                  case 0x0:
304                    return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
305                  case 0x1:
306                    return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
307                  case 0x2:
308                    return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
309                  case 0x3:
310                    return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
311                  case 0x4:
312                    return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
313                  case 0x7:
314                    return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
315                }
316                break;
317              case 0x3:
318                switch (op2) {
319                  case 0x0:
320                    return new WarnUnimplemented("uhadd16", machInst);
321                  case 0x1:
322                    return new WarnUnimplemented("uhasx", machInst);
323                  case 0x2:
324                    return new WarnUnimplemented("uhsax", machInst);
325                  case 0x3:
326                    return new WarnUnimplemented("uhsub16", machInst);
327                  case 0x4:
328                    return new WarnUnimplemented("uhadd8", machInst);
329                  case 0x7:
330                    return new WarnUnimplemented("uhsub8", machInst);
331                }
332                break;
333            }
334        }
335        return new Unknown(machInst);
336    }
337    '''
338}};
339
340def format ArmDataProcImm() {{
341    pclr = '''
342        return new %(className)ssImmPclr(machInst, %(dest)s,
343                                        %(op1)s, imm, false);
344    '''
345    adr = '''
346        return new AdrImm(machInst, %(dest)s, %(add)s,
347                                     imm, false);
348    '''
349    instDecode = '''
350          case %(opcode)#x:
351            if (setCc) {
352                if (%(pclrInst)s && %(dest)s == INTREG_PC) {
353                    %(pclr)s
354                } else {
355                    return new %(className)sImmCc(machInst, %(dest)s, %(op1)s,
356                                                   imm, rotC);
357                }
358            } else {
359                if (%(adrInst)s && %(op1)s == INTREG_PC) {
360                    %(adr)s
361                } else {
362                    return new %(className)sImm(machInst, %(dest)s, %(op1)s,
363                                                 imm, rotC);
364                }
365            }
366            break;
367    '''
368
369    def instCode(opcode, mnem, useDest = True, useOp1 = True):
370        global instDecode, pclr, adr
371        if useDest:
372            dest = "rd"
373        else:
374            dest = "INTREG_ZERO"
375        if useOp1:
376            op1 = "rn"
377        else:
378            op1 = "INTREG_ZERO"
379        substDict = { "className": mnem.capitalize(),
380                      "opcode": opcode,
381                      "dest": dest,
382                      "op1": op1,
383                      "adr": "",
384                      "adrInst": "false" }
385        if useDest:
386            substDict["pclrInst"] = "true"
387            substDict["pclr"] = pclr % substDict
388        else:
389            substDict["pclrInst"] = "false"
390            substDict["pclr"] = ""
391        return instDecode % substDict
392
393    def adrCode(opcode, mnem, add="1"):
394        global instDecode, pclr, adr
395        substDict = { "className": mnem.capitalize(),
396                      "opcode": opcode,
397                      "dest": "rd",
398                      "op1": "rn",
399                      "add": add,
400                      "pclrInst": "true",
401                      "adrInst": "true" }
402        substDict["pclr"] = pclr % substDict
403        substDict["adr"] = adr % substDict
404        return instDecode % substDict
405
406    decode_block = '''
407    {
408        const bool setCc = (bits(machInst, 20) == 1);
409        const uint32_t unrotated = bits(machInst, 7, 0);
410        const uint32_t rotation = (bits(machInst, 11, 8) << 1);
411        const bool rotC = (rotation != 0);
412        const uint32_t imm = rotate_imm(unrotated, rotation);
413        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
414        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
415        switch (OPCODE) {
416    '''
417    decode_block += instCode(0x0, "and")
418    decode_block += instCode(0x1, "eor")
419    decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0")
420    decode_block += instCode(0x3, "rsb")
421    decode_block += adrCode(0x4, "add", add="(IntRegIndex)1")
422    decode_block += instCode(0x5, "adc")
423    decode_block += instCode(0x6, "sbc")
424    decode_block += instCode(0x7, "rsc")
425    decode_block += instCode(0x8, "tst", useDest = False)
426    decode_block += instCode(0x9, "teq", useDest = False)
427    decode_block += instCode(0xa, "cmp", useDest = False)
428    decode_block += instCode(0xb, "cmn", useDest = False)
429    decode_block += instCode(0xc, "orr")
430    decode_block += instCode(0xd, "mov", useOp1 = False)
431    decode_block += instCode(0xe, "bic")
432    decode_block += instCode(0xf, "mvn", useOp1 = False)
433    decode_block += '''
434          default:
435            return new Unknown(machInst);
436        }
437    }
438    '''
439}};
440
441def format ArmSatAddSub() {{
442    decode_block = '''
443    {
444        IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
445        IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
446        IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
447        switch (OPCODE) {
448          case 0x8:
449            return new QaddRegCc(machInst, rd, rm, rn, 0, LSL);
450          case 0x9:
451            return new QsubRegCc(machInst, rd, rm, rn, 0, LSL);
452          case 0xa:
453            return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL);
454          case 0xb:
455            return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL);
456          default:
457            return new Unknown(machInst);
458        }
459    }
460    '''
461}};
462
463def format Thumb32DataProcReg() {{
464    decode_block = '''
465    {
466        const uint32_t op1 = bits(machInst, 23, 20);
467        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
468        const uint32_t op2 = bits(machInst, 7, 4);
469        if (bits(op1, 3) != 1) {
470            if (op2 == 0) {
471                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
472                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
473                switch (bits(op1, 2, 0)) {
474                  case 0x0:
475                    return new MovRegReg(machInst, rd,
476                            INTREG_ZERO, rn, rm, LSL);
477                  case 0x1:
478                    return new MovRegRegCc(machInst, rd,
479                            INTREG_ZERO, rn, rm, LSL);
480                  case 0x2:
481                    return new MovRegReg(machInst, rd,
482                            INTREG_ZERO, rn, rm, LSR);
483                  case 0x3:
484                    return new MovRegRegCc(machInst, rd,
485                            INTREG_ZERO, rn, rm, LSR);
486                  case 0x4:
487                    return new MovRegReg(machInst, rd,
488                            INTREG_ZERO, rn, rm, ASR);
489                  case 0x5:
490                    return new MovRegRegCc(machInst, rd,
491                            INTREG_ZERO, rn, rm, ASR);
492                  case 0x6:
493                    return new MovRegReg(machInst, rd,
494                            INTREG_ZERO, rn, rm, ROR);
495                  case 0x7:
496                    return new MovRegRegCc(machInst, rd,
497                            INTREG_ZERO, rn, rm, ROR);
498                }
499            }
500            switch (bits(op1, 2, 0)) {
501              case 0x0:
502                if (rn == 0xf) {
503                    return new WarnUnimplemented("sxth", machInst);
504                } else {
505                    return new WarnUnimplemented("sxtah", machInst);
506                }
507              case 0x1:
508                if (rn == 0xf) {
509                    return new WarnUnimplemented("uxth", machInst);
510                } else {
511                    return new WarnUnimplemented("uxtah", machInst);
512                }
513              case 0x2:
514                if (rn == 0xf) {
515                    return new WarnUnimplemented("sxtb16", machInst);
516                } else {
517                    return new WarnUnimplemented("sxtab16", machInst);
518                }
519              case 0x3:
520                if (rn == 0xf) {
521                    return new WarnUnimplemented("uxtb16", machInst);
522                } else {
523                    return new WarnUnimplemented("uxtab16", machInst);
524                }
525              case 0x4:
526                if (rn == 0xf) {
527                    return new WarnUnimplemented("sxtb", machInst);
528                } else {
529                    return new WarnUnimplemented("sxtab", machInst);
530                }
531              case 0x5:
532                if (rn == 0xf) {
533                    return new WarnUnimplemented("uxtb", machInst);
534                } else {
535                    return new WarnUnimplemented("uxtab", machInst);
536                }
537              default:
538                return new Unknown(machInst);
539            }
540        } else {
541            if (bits(op2, 3) == 0) {
542                const IntRegIndex rd =
543                    (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
544                const IntRegIndex rm =
545                    (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
546                if (bits(op2, 2) == 0x0) {
547                    const uint32_t op1 = bits(machInst, 22, 20);
548                    const uint32_t op2 = bits(machInst, 5, 4);
549                    switch (op2) {
550                      case 0x0:
551                        switch (op1) {
552                          case 0x1:
553                            return new Sadd16RegCc(machInst, rd,
554                                                   rn, rm, 0, LSL);
555                          case 0x2:
556                            return new SasxRegCc(machInst, rd,
557                                                 rn, rm, 0, LSL);
558                          case 0x6:
559                            return new SsaxRegCc(machInst, rd,
560                                                 rn, rm, 0, LSL);
561                          case 0x5:
562                            return new Ssub16RegCc(machInst, rd,
563                                                   rn, rm, 0, LSL);
564                          case 0x0:
565                            return new Sadd8RegCc(machInst, rd,
566                                                  rn, rm, 0, LSL);
567                          case 0x4:
568                            return new Ssub8RegCc(machInst, rd,
569                                                  rn, rm, 0, LSL);
570                        }
571                        break;
572                      case 0x1:
573                        switch (op1) {
574                          case 0x1:
575                            return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
576                          case 0x2:
577                            return new QasxReg(machInst, rd, rn, rm, 0, LSL);
578                          case 0x6:
579                            return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
580                          case 0x5:
581                            return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
582                          case 0x0:
583                            return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
584                          case 0x4:
585                            return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
586                        }
587                        break;
588                      case 0x2:
589                        switch (op1) {
590                          case 0x1:
591                            return new WarnUnimplemented("shadd16", machInst);
592                          case 0x2:
593                            return new WarnUnimplemented("shasx", machInst);
594                          case 0x6:
595                            return new WarnUnimplemented("shsax", machInst);
596                          case 0x5:
597                            return new WarnUnimplemented("shsub16", machInst);
598                          case 0x0:
599                            return new WarnUnimplemented("shadd8", machInst);
600                          case 0x4:
601                            return new WarnUnimplemented("shsub8", machInst);
602                        }
603                        break;
604                    }
605                } else {
606                    const uint32_t op1 = bits(machInst, 22, 20);
607                    const uint32_t op2 = bits(machInst, 5, 4);
608                    switch (op2) {
609                      case 0x0:
610                        switch (op1) {
611                          case 0x1:
612                            return new Uadd16RegCc(machInst, rd,
613                                                   rn, rm, 0, LSL);
614                          case 0x2:
615                            return new UasxRegCc(machInst, rd,
616                                                 rn, rm, 0, LSL);
617                          case 0x6:
618                            return new UsaxRegCc(machInst, rd,
619                                                 rn, rm, 0, LSL);
620                          case 0x5:
621                            return new Usub16RegCc(machInst, rd,
622                                                   rn, rm, 0, LSL);
623                          case 0x0:
624                            return new Uadd8RegCc(machInst, rd,
625                                                  rn, rm, 0, LSL);
626                          case 0x4:
627                            return new Usub8RegCc(machInst, rd,
628                                                  rn, rm, 0, LSL);
629                        }
630                        break;
631                      case 0x1:
632                        switch (op1) {
633                          case 0x1:
634                            return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL);
635                          case 0x2:
636                            return new UqasxReg(machInst, rd, rn, rm, 0, LSL);
637                          case 0x6:
638                            return new UqsaxReg(machInst, rd, rn, rm, 0, LSL);
639                          case 0x5:
640                            return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL);
641                          case 0x0:
642                            return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL);
643                          case 0x4:
644                            return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL);
645                        }
646                        break;
647                      case 0x2:
648                        switch (op1) {
649                          case 0x1:
650                            return new WarnUnimplemented("uhadd16", machInst);
651                          case 0x2:
652                            return new WarnUnimplemented("uhasx", machInst);
653                          case 0x6:
654                            return new WarnUnimplemented("uhsax", machInst);
655                          case 0x5:
656                            return new WarnUnimplemented("uhsub16", machInst);
657                          case 0x0:
658                            return new WarnUnimplemented("uhadd8", machInst);
659                          case 0x4:
660                            return new WarnUnimplemented("uhsub8", machInst);
661                        }
662                        break;
663                    }
664                }
665            } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) {
666                const uint32_t op1 = bits(machInst, 21, 20);
667                const uint32_t op2 = bits(machInst, 5, 4);
668                switch (op1) {
669                  case 0x0:
670                    {
671                        IntRegIndex rd =
672                            (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
673                        IntRegIndex rm =
674                            (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
675                        switch (op2) {
676                          case 0x0:
677                            return new QaddRegCc(machInst, rd,
678                                                 rm, rn, 0, LSL);
679                          case 0x1:
680                            return new QdaddRegCc(machInst, rd,
681                                                  rm, rn, 0, LSL);
682                          case 0x2:
683                            return new QsubRegCc(machInst, rd,
684                                                 rm, rn, 0, LSL);
685                          case 0x3:
686                            return new QdsubRegCc(machInst, rd,
687                                                  rm, rn, 0, LSL);
688                        }
689                    }
690                    break;
691                  case 0x1:
692                    {
693                        IntRegIndex rd =
694                            (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
695                        IntRegIndex rm = rn;
696                        switch (op2) {
697                          case 0x0:
698                            return new Rev(machInst, rd, rm);
699                          case 0x1:
700                            return new Rev16(machInst, rd, rm);
701                          case 0x2:
702                            return new WarnUnimplemented("rbit", machInst);
703                          case 0x3:
704                            return new Revsh(machInst, rd, rm);
705                        }
706                    }
707                    break;
708                  case 0x2:
709                    if (op2 == 0) {
710                        return new WarnUnimplemented("sel", machInst);
711                    }
712                    break;
713                  case 0x3:
714                    if (op2 == 0) {
715                        return new WarnUnimplemented("clz", machInst);
716                    }
717                }
718            }
719            return new Unknown(machInst);
720        }
721    }
722    '''
723}};
724
725def format Thumb16ShiftAddSubMoveCmp() {{
726    decode_block = '''
727    {
728        const uint32_t imm5 = bits(machInst, 10, 6);
729        const uint32_t imm3 = bits(machInst, 8, 6);
730        const uint32_t imm8 = bits(machInst, 7, 0);
731        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
732        const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
733        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
734        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
735        switch (bits(machInst, 13, 11)) {
736          case 0x0: // lsl
737            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
738          case 0x1: // lsr
739            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
740          case 0x2: // asr
741            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
742          case 0x3:
743            switch (bits(machInst, 10, 9)) {
744              case 0x0:
745                return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
746              case 0x1:
747                return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
748              case 0x2:
749                return new AddImmCc(machInst, rd, rn, imm3, true);
750              case 0x3:
751                return new SubImmCc(machInst, rd, rn, imm3, true);
752            }
753          case 0x4:
754            return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
755          case 0x5:
756            return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
757          case 0x6:
758            return new AddImmCc(machInst, rd8, rd8, imm8, true);
759          case 0x7:
760            return new SubImmCc(machInst, rd8, rd8, imm8, true);
761        }
762    }
763    '''
764}};
765
766def format Thumb16DataProcessing() {{
767    decode_block = '''
768    {
769        const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
770        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
771        switch (bits(machInst, 9, 6)) {
772          case 0x0:
773            return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
774          case 0x1:
775            return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
776          case 0x2: //lsl
777            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
778          case 0x3: //lsr
779            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
780          case 0x4: //asr
781            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
782          case 0x5:
783            return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
784          case 0x6:
785            return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
786          case 0x7: // ror
787            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
788          case 0x8:
789            return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
790          case 0x9:
791            return new RsbImmCc(machInst, rdn, rm, 0, true);
792          case 0xa:
793            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
794          case 0xb:
795            return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
796          case 0xc:
797            return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
798          case 0xd:
799            return new MulCc(machInst, rdn, rm, rdn);
800          case 0xe:
801            return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
802          case 0xf:
803            return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
804        }
805    }
806    '''
807}};
808
809def format Thumb16SpecDataAndBx() {{
810    decode_block = '''
811    {
812        const IntRegIndex rdn =
813            (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
814                                    (bits(machInst, 7) << 3));
815        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
816        switch (bits(machInst, 9, 8)) {
817          case 0x0:
818            return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
819          case 0x1:
820            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
821          case 0x2:
822            return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
823          case 0x3:
824            if (bits(machInst, 7) == 0) {
825                return new BxReg(machInst,
826                                 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
827                                 COND_UC);
828            } else {
829                return new BlxReg(machInst,
830                                  (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
831                                  COND_UC);
832            }
833        }
834    }
835    '''
836}};
837
838def format Thumb16Adr() {{
839    decode_block = '''
840    {
841        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
842        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
843        return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
844    }
845    '''
846}};
847
848def format Thumb16AddSp() {{
849    decode_block = '''
850    {
851        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
852        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
853        return new AddImm(machInst, rd, INTREG_SP, imm8, true);
854    }
855    '''
856}};
857
858def format Thumb16Misc() {{
859    decode_block = '''
860    {
861        switch (bits(machInst, 11, 8)) {
862          case 0x0:
863            if (bits(machInst, 7)) {
864                return new SubImm(machInst, INTREG_SP, INTREG_SP,
865                                   bits(machInst, 6, 0) << 2, true);
866            } else {
867                return new AddImm(machInst, INTREG_SP, INTREG_SP,
868                                   bits(machInst, 6, 0) << 2, true);
869            }
870          case 0x1:
871            return new Cbz(machInst,
872                           (bits(machInst, 9) << 6) |
873                           (bits(machInst, 7, 3) << 1),
874                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
875          case 0x2:
876            switch (bits(machInst, 7, 6)) {
877              case 0x0:
878                return new WarnUnimplemented("sxth", machInst);
879              case 0x1:
880                return new WarnUnimplemented("sxtb", machInst);
881              case 0x2:
882                return new WarnUnimplemented("uxth", machInst);
883              case 0x3:
884                return new WarnUnimplemented("uxtb", machInst);
885            }
886          case 0x3:
887            return new Cbz(machInst,
888                           (bits(machInst, 9) << 6) |
889                           (bits(machInst, 7, 3) << 1),
890                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
891          case 0x4:
892          case 0x5:
893            {
894                const uint32_t m = bits(machInst, 8);
895                const uint32_t regList = bits(machInst, 7, 0) | (m << 14);
896                return new LdmStm(machInst, INTREG_SP, false, false, false,
897                                  true, false, regList);
898            }
899          case 0x6:
900            {
901                const uint32_t opBits = bits(machInst, 7, 5);
902                if (opBits == 2) {
903                    return new WarnUnimplemented("setend", machInst);
904                } else if (opBits == 3) {
905                    return new WarnUnimplemented("cps", machInst);
906                }
907            }
908          case 0x9:
909            return new Cbnz(machInst,
910                            (bits(machInst, 9) << 6) |
911                            (bits(machInst, 7, 3) << 1),
912                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
913          case 0xa:
914            {
915                IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
916                IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
917                switch (bits(machInst, 7, 6)) {
918                  case 0x0:
919                    return new Rev(machInst, rd, rm);
920                  case 0x1:
921                    return new Rev16(machInst, rd, rm);
922                  case 0x3:
923                    return new Revsh(machInst, rd, rm);
924                  default:
925                    break;
926                }
927            }
928            break;
929          case 0xb:
930            return new Cbnz(machInst,
931                            (bits(machInst, 9) << 6) |
932                            (bits(machInst, 7, 3) << 1),
933                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
934          case 0xc:
935          case 0xd:
936            {
937                const uint32_t p = bits(machInst, 8);
938                const uint32_t regList = bits(machInst, 7, 0) | (p << 15);
939                return new LdmStm(machInst, INTREG_SP, true, true, false,
940                                  true, true, regList);
941            }
942          case 0xe:
943            return new WarnUnimplemented("bkpt", machInst);
944          case 0xf:
945            if (bits(machInst, 3, 0) != 0)
946                return new WarnUnimplemented("it", machInst);
947            switch (bits(machInst, 7, 4)) {
948              case 0x0:
949                return new WarnUnimplemented("nop", machInst);
950              case 0x1:
951                return new WarnUnimplemented("yield", machInst);
952              case 0x2:
953                return new WarnUnimplemented("wfe", machInst);
954              case 0x3:
955                return new WarnUnimplemented("wfi", machInst);
956              case 0x4:
957                return new WarnUnimplemented("sev", machInst);
958              default:
959                return new WarnUnimplemented("unallocated_hint", machInst);
960            }
961          default:
962            break;
963        }
964        return new Unknown(machInst);
965    }
966    '''
967}};
968
969def format Thumb32DataProcModImm() {{
970
971    def decInst(mnem, dest="rd", op1="rn"):
972        return '''
973            if (s) {
974                return new %(mnem)sImmCc(machInst, %(dest)s,
975                                          %(op1)s, imm, rotC);
976            } else {
977                return new %(mnem)sImm(machInst, %(dest)s,
978                                        %(op1)s, imm, rotC);
979            }
980        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
981
982    decode_block = '''
983    {
984        const uint32_t op = bits(machInst, 24, 21);
985        const bool s = (bits(machInst, 20) == 1);
986        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
987        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
988        const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
989                                 bits(machInst, 14, 12);
990        const bool rotC = ctrlImm > 3;
991        const uint32_t dataImm = bits(machInst, 7, 0);
992        const uint32_t imm = modified_imm(ctrlImm, dataImm);
993        switch (op) {
994          case 0x0:
995            if (rd == INTREG_PC) {
996                %(tst)s
997            } else {
998                %(and)s
999            }
1000          case 0x1:
1001            %(bic)s
1002          case 0x2:
1003            if (rn == INTREG_PC) {
1004                %(mov)s
1005            } else {
1006                %(orr)s
1007            }
1008          case 0x3:
1009            if (rn == INTREG_PC) {
1010                %(mvn)s
1011            } else {
1012                %(orn)s
1013            }
1014          case 0x4:
1015            if (rd == INTREG_PC) {
1016                %(teq)s
1017            } else {
1018                %(eor)s
1019            }
1020          case 0x8:
1021            if (rd == INTREG_PC) {
1022                %(cmn)s
1023            } else {
1024                %(add)s
1025            }
1026          case 0xa:
1027            %(adc)s
1028          case 0xb:
1029            %(sbc)s
1030          case 0xd:
1031            if (rd == INTREG_PC) {
1032                %(cmp)s
1033            } else {
1034                %(sub)s
1035            }
1036          case 0xe:
1037            %(rsb)s
1038          default:
1039            return new Unknown(machInst);
1040        }
1041    }
1042    ''' % {
1043        "tst" : decInst("Tst", "INTREG_ZERO"),
1044        "and" : decInst("And"),
1045        "bic" : decInst("Bic"),
1046        "mov" : decInst("Mov", op1="INTREG_ZERO"),
1047        "orr" : decInst("Orr"),
1048        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1049        "orn" : decInst("Orn"),
1050        "teq" : decInst("Teq", dest="INTREG_ZERO"),
1051        "eor" : decInst("Eor"),
1052        "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
1053        "add" : decInst("Add"),
1054        "adc" : decInst("Adc"),
1055        "sbc" : decInst("Sbc"),
1056        "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
1057        "sub" : decInst("Sub"),
1058        "rsb" : decInst("Rsb")
1059    }
1060}};
1061
1062def format Thumb32DataProcPlainBin() {{
1063    decode_block = '''
1064    {
1065        const uint32_t op = bits(machInst, 24, 20);
1066        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1067        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1068        switch (op) {
1069          case 0x0:
1070            {
1071                const uint32_t imm = bits(machInst, 7, 0) |
1072                                     (bits(machInst, 14, 12) << 8) |
1073                                     (bits(machInst, 26) << 11);
1074                if (rn == 0xf) {
1075                    return new AdrImm(machInst, rd, (IntRegIndex)1,
1076                                      imm, false);
1077                } else {
1078                    return new AddImm(machInst, rd, rn, imm, true);
1079                }
1080            }
1081          case 0x4:
1082            {
1083                const uint32_t imm = bits(machInst, 7, 0) |
1084                                     (bits(machInst, 14, 12) << 8) |
1085                                     (bits(machInst, 26) << 11) |
1086                                     (bits(machInst, 19, 16) << 12);
1087                return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
1088            }
1089          case 0xa:
1090            {
1091                const uint32_t imm = bits(machInst, 7, 0) |
1092                                     (bits(machInst, 14, 12) << 8) |
1093                                     (bits(machInst, 26) << 11);
1094                if (rn == 0xf) {
1095                    return new AdrImm(machInst, rd, (IntRegIndex)0,
1096                                      imm, false);
1097                } else {
1098                    return new SubImm(machInst, rd, rn, imm, true);
1099                }
1100            }
1101          case 0xc:
1102            {
1103                const uint32_t imm = bits(machInst, 7, 0) |
1104                                     (bits(machInst, 14, 12) << 8) |
1105                                     (bits(machInst, 26) << 11) |
1106                                     (bits(machInst, 19, 16) << 12);
1107                return new MovtImm(machInst, rd, rd, imm, true);
1108            }
1109          case 0x12:
1110            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1111                return new WarnUnimplemented("ssat16", machInst);
1112            }
1113            // Fall through on purpose...
1114          case 0x10:
1115            return new WarnUnimplemented("ssat", machInst);
1116          case 0x14:
1117            return new WarnUnimplemented("sbfx", machInst);
1118          case 0x16:
1119            if (rn == 0xf) {
1120                return new WarnUnimplemented("bfc", machInst);
1121            } else {
1122                return new WarnUnimplemented("bfi", machInst);
1123            }
1124          case 0x1a:
1125            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
1126                return new WarnUnimplemented("usat16", machInst);
1127            }
1128            // Fall through on purpose...
1129          case 0x18:
1130            return new WarnUnimplemented("usat", machInst);
1131          case 0x1c:
1132            return new WarnUnimplemented("ubfx", machInst);
1133          default:
1134            return new Unknown(machInst);
1135        }
1136    }
1137    '''
1138}};
1139
1140def format Thumb32DataProcShiftReg() {{
1141
1142    def decInst(mnem, dest="rd", op1="rn"):
1143        return '''
1144            if (s) {
1145                return new %(mnem)sRegCc(machInst, %(dest)s,
1146                                          %(op1)s, rm, amt, type);
1147            } else {
1148                return new %(mnem)sReg(machInst, %(dest)s,
1149                                        %(op1)s, rm, amt, type);
1150            }
1151        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
1152
1153    decode_block = '''
1154    {
1155        const uint32_t op = bits(machInst, 24, 21);
1156        const bool s = (bits(machInst, 20) == 1);
1157        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1158        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
1159        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
1160        const uint32_t amt = (bits(machInst, 14, 12) << 2) |
1161                              bits(machInst, 7, 6);
1162        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
1163        switch (op) {
1164          case 0x0:
1165            if (rd == INTREG_PC) {
1166                %(tst)s
1167            } else {
1168                %(and)s
1169            }
1170          case 0x1:
1171            %(bic)s
1172          case 0x2:
1173            if (rn == INTREG_PC) {
1174                %(mov)s
1175            } else {
1176                %(orr)s
1177            }
1178          case 0x3:
1179            if (rn == INTREG_PC) {
1180                %(mvn)s
1181            } else {
1182                %(orn)s
1183            }
1184          case 0x4:
1185            if (rd == INTREG_PC) {
1186                %(teq)s
1187            } else {
1188                %(eor)s
1189            }
1190          case 0x6:
1191            return new WarnUnimplemented("pkh", machInst);
1192          case 0x8:
1193            if (rd == INTREG_PC) {
1194                %(cmn)s
1195            } else {
1196                %(add)s
1197            }
1198          case 0xa:
1199            %(adc)s
1200          case 0xb:
1201            %(sbc)s
1202          case 0xd:
1203            if (rd == INTREG_PC) {
1204                %(cmp)s
1205            } else {
1206                %(sub)s
1207            }
1208          case 0xe:
1209            %(rsb)s
1210          default:
1211            return new Unknown(machInst);
1212        }
1213    }
1214    ''' % {
1215        "tst" : decInst("Tst", "INTREG_ZERO"),
1216        "and" : decInst("And"),
1217        "bic" : decInst("Bic"),
1218        "mov" : decInst("Mov", op1="INTREG_ZERO"),
1219        "orr" : decInst("Orr"),
1220        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
1221        "orn" : decInst("Orn"),
1222        "teq" : decInst("Teq", "INTREG_ZERO"),
1223        "eor" : decInst("Eor"),
1224        "cmn" : decInst("Cmn", "INTREG_ZERO"),
1225        "add" : decInst("Add"),
1226        "adc" : decInst("Adc"),
1227        "sbc" : decInst("Sbc"),
1228        "cmp" : decInst("Cmp", "INTREG_ZERO"),
1229        "sub" : decInst("Sub"),
1230        "rsb" : decInst("Rsb")
1231    }
1232}};
1233