data.isa revision 7194:f72dc8789553
17119Sgblack@eecs.umich.edu// Copyright (c) 2010 ARM Limited
27119Sgblack@eecs.umich.edu// All rights reserved
37119Sgblack@eecs.umich.edu//
47119Sgblack@eecs.umich.edu// The license below extends only to copyright in the software and shall
57119Sgblack@eecs.umich.edu// not be construed as granting a license to any other intellectual
67119Sgblack@eecs.umich.edu// property including but not limited to intellectual property relating
77119Sgblack@eecs.umich.edu// to a hardware implementation of the functionality of the software
87119Sgblack@eecs.umich.edu// licensed hereunder.  You may use the software subject to the license
97119Sgblack@eecs.umich.edu// terms below provided that you ensure that this notice is replicated
107119Sgblack@eecs.umich.edu// unmodified and in its entirety in all distributions of the software,
117119Sgblack@eecs.umich.edu// modified or unmodified, in source code or in binary form.
127119Sgblack@eecs.umich.edu//
137119Sgblack@eecs.umich.edu// Redistribution and use in source and binary forms, with or without
147119Sgblack@eecs.umich.edu// modification, are permitted provided that the following conditions are
157119Sgblack@eecs.umich.edu// met: redistributions of source code must retain the above copyright
167119Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer;
177119Sgblack@eecs.umich.edu// redistributions in binary form must reproduce the above copyright
187119Sgblack@eecs.umich.edu// notice, this list of conditions and the following disclaimer in the
197119Sgblack@eecs.umich.edu// documentation and/or other materials provided with the distribution;
207119Sgblack@eecs.umich.edu// neither the name of the copyright holders nor the names of its
217119Sgblack@eecs.umich.edu// contributors may be used to endorse or promote products derived from
227119Sgblack@eecs.umich.edu// this software without specific prior written permission.
237119Sgblack@eecs.umich.edu//
247119Sgblack@eecs.umich.edu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
257119Sgblack@eecs.umich.edu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
267119Sgblack@eecs.umich.edu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
277119Sgblack@eecs.umich.edu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
287119Sgblack@eecs.umich.edu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
297119Sgblack@eecs.umich.edu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
307119Sgblack@eecs.umich.edu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
317119Sgblack@eecs.umich.edu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
327119Sgblack@eecs.umich.edu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
337119Sgblack@eecs.umich.edu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
347119Sgblack@eecs.umich.edu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
357119Sgblack@eecs.umich.edu//
367119Sgblack@eecs.umich.edu// Authors: Gabe Black
377119Sgblack@eecs.umich.edu
387119Sgblack@eecs.umich.edudef format ArmDataProcReg() {{
397119Sgblack@eecs.umich.edu    pclr = '''
407119Sgblack@eecs.umich.edu        return new %(className)ssRegPclr(machInst, %(dest)s,
417119Sgblack@eecs.umich.edu                                        %(op1)s, rm, imm5,
427119Sgblack@eecs.umich.edu                                        type);
437119Sgblack@eecs.umich.edu    '''
447119Sgblack@eecs.umich.edu    instDecode = '''
457119Sgblack@eecs.umich.edu          case %(opcode)#x:
467119Sgblack@eecs.umich.edu            if (immShift) {
477119Sgblack@eecs.umich.edu                if (setCc) {
487119Sgblack@eecs.umich.edu                    if (%(dest)s == INTREG_PC) {
497119Sgblack@eecs.umich.edu                        %(pclr)s
507119Sgblack@eecs.umich.edu                    } else {
517119Sgblack@eecs.umich.edu                        return new %(className)sRegCc(machInst, %(dest)s,
527119Sgblack@eecs.umich.edu                                                      %(op1)s, rm, imm5, type);
537119Sgblack@eecs.umich.edu                    }
547119Sgblack@eecs.umich.edu                } else {
557119Sgblack@eecs.umich.edu                    return new %(className)sReg(machInst, %(dest)s, %(op1)s,
567119Sgblack@eecs.umich.edu                                                 rm, imm5, type);
577119Sgblack@eecs.umich.edu                }
587119Sgblack@eecs.umich.edu            } else {
597119Sgblack@eecs.umich.edu                if (setCc) {
607119Sgblack@eecs.umich.edu                    return new %(className)sRegRegCc(machInst, %(dest)s,
617119Sgblack@eecs.umich.edu                                                      %(op1)s, rm, rs, type);
627119Sgblack@eecs.umich.edu                } else {
637119Sgblack@eecs.umich.edu                    return new %(className)sRegReg(machInst, %(dest)s,
647119Sgblack@eecs.umich.edu                                                    %(op1)s, rm, rs, type);
657119Sgblack@eecs.umich.edu                }
667119Sgblack@eecs.umich.edu            }
677119Sgblack@eecs.umich.edu            break;
687119Sgblack@eecs.umich.edu    '''
697119Sgblack@eecs.umich.edu
707119Sgblack@eecs.umich.edu    def instCode(opcode, mnem, useDest = True, useOp1 = True):
717119Sgblack@eecs.umich.edu        global pclr
727119Sgblack@eecs.umich.edu        if useDest:
737119Sgblack@eecs.umich.edu            dest = "rd"
747119Sgblack@eecs.umich.edu        else:
757119Sgblack@eecs.umich.edu            dest = "INTREG_ZERO"
767119Sgblack@eecs.umich.edu        if useOp1:
777119Sgblack@eecs.umich.edu            op1 = "rn"
787119Sgblack@eecs.umich.edu        else:
797119Sgblack@eecs.umich.edu            op1 = "INTREG_ZERO"
807119Sgblack@eecs.umich.edu        global instDecode, pclrCode
817119Sgblack@eecs.umich.edu        substDict = { "className": mnem.capitalize(),
827119Sgblack@eecs.umich.edu                      "opcode": opcode,
837119Sgblack@eecs.umich.edu                      "dest": dest,
847119Sgblack@eecs.umich.edu                      "op1": op1 }
857119Sgblack@eecs.umich.edu        if useDest:
867119Sgblack@eecs.umich.edu            substDict["pclr"] = pclr % substDict
877119Sgblack@eecs.umich.edu        else:
887119Sgblack@eecs.umich.edu            substDict["pclr"] = ""
897119Sgblack@eecs.umich.edu        return instDecode % substDict
907119Sgblack@eecs.umich.edu
917119Sgblack@eecs.umich.edu    decode_block = '''
927119Sgblack@eecs.umich.edu    {
937119Sgblack@eecs.umich.edu        const bool immShift = (bits(machInst, 4) == 0);
947119Sgblack@eecs.umich.edu        const bool setCc = (bits(machInst, 20) == 1);
957119Sgblack@eecs.umich.edu        const uint32_t imm5 = bits(machInst, 11, 7);
967119Sgblack@eecs.umich.edu        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5);
977119Sgblack@eecs.umich.edu        const IntRegIndex rd = (IntRegIndex)(uint32_t)RD;
987119Sgblack@eecs.umich.edu        const IntRegIndex rn = (IntRegIndex)(uint32_t)RN;
997119Sgblack@eecs.umich.edu        const IntRegIndex rm = (IntRegIndex)(uint32_t)RM;
1007119Sgblack@eecs.umich.edu        const IntRegIndex rs = (IntRegIndex)(uint32_t)RS;
1017119Sgblack@eecs.umich.edu        switch (OPCODE) {
1027119Sgblack@eecs.umich.edu    '''
1037119Sgblack@eecs.umich.edu    decode_block += instCode(0x0, "and")
1047119Sgblack@eecs.umich.edu    decode_block += instCode(0x1, "eor")
1057119Sgblack@eecs.umich.edu    decode_block += instCode(0x2, "sub")
1067119Sgblack@eecs.umich.edu    decode_block += instCode(0x3, "rsb")
1077119Sgblack@eecs.umich.edu    decode_block += instCode(0x4, "add")
1087119Sgblack@eecs.umich.edu    decode_block += instCode(0x5, "adc")
1097119Sgblack@eecs.umich.edu    decode_block += instCode(0x6, "sbc")
1107119Sgblack@eecs.umich.edu    decode_block += instCode(0x7, "rsc")
1117119Sgblack@eecs.umich.edu    decode_block += instCode(0x8, "tst", useDest = False)
1127119Sgblack@eecs.umich.edu    decode_block += instCode(0x9, "teq", useDest = False)
1137119Sgblack@eecs.umich.edu    decode_block += instCode(0xa, "cmp", useDest = False)
1147119Sgblack@eecs.umich.edu    decode_block += instCode(0xb, "cmn", useDest = False)
1157119Sgblack@eecs.umich.edu    decode_block += instCode(0xc, "orr")
1167119Sgblack@eecs.umich.edu    decode_block += instCode(0xd, "mov", useOp1 = False)
1177119Sgblack@eecs.umich.edu    decode_block += instCode(0xe, "bic")
1187119Sgblack@eecs.umich.edu    decode_block += instCode(0xf, "mvn", useOp1 = False)
1197119Sgblack@eecs.umich.edu    decode_block += '''
1207119Sgblack@eecs.umich.edu          default:
1217119Sgblack@eecs.umich.edu            return new Unknown(machInst);
1227119Sgblack@eecs.umich.edu        }
1237119Sgblack@eecs.umich.edu    }
1247119Sgblack@eecs.umich.edu    '''
1257119Sgblack@eecs.umich.edu}};
1267119Sgblack@eecs.umich.edu
1277119Sgblack@eecs.umich.edudef format ArmParallelAddSubtract() {{
1287119Sgblack@eecs.umich.edu    decode_block='''
1297119Sgblack@eecs.umich.edu    {
1307119Sgblack@eecs.umich.edu        const uint32_t op1 = bits(machInst, 21, 20);
1317119Sgblack@eecs.umich.edu        const uint32_t op2 = bits(machInst, 7, 5);
1327119Sgblack@eecs.umich.edu        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
1337119Sgblack@eecs.umich.edu        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
1347119Sgblack@eecs.umich.edu        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
1357119Sgblack@eecs.umich.edu        if (bits(machInst, 22) == 0) {
1367119Sgblack@eecs.umich.edu            switch (op1) {
1377119Sgblack@eecs.umich.edu              case 0x1:
1387119Sgblack@eecs.umich.edu                switch (op2) {
1397119Sgblack@eecs.umich.edu                  case 0x0:
1407119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("sadd16", machInst);
1417119Sgblack@eecs.umich.edu                  case 0x1:
1427119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("sasx", machInst);
1437119Sgblack@eecs.umich.edu                  case 0x2:
1447119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("ssax", machInst);
1457119Sgblack@eecs.umich.edu                  case 0x3:
1467119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("ssub16", machInst);
1477119Sgblack@eecs.umich.edu                  case 0x4:
1487119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("sadd8", machInst);
1497119Sgblack@eecs.umich.edu                  case 0x7:
1507119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("ssub8", machInst);
1517119Sgblack@eecs.umich.edu                }
1527119Sgblack@eecs.umich.edu                break;
1537119Sgblack@eecs.umich.edu              case 0x2:
1547119Sgblack@eecs.umich.edu                switch (op2) {
1557119Sgblack@eecs.umich.edu                  case 0x0:
1567119Sgblack@eecs.umich.edu                    return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL);
1577119Sgblack@eecs.umich.edu                  case 0x1:
1587119Sgblack@eecs.umich.edu                    return new QasxReg(machInst, rd, rn, rm, 0, LSL);
1597119Sgblack@eecs.umich.edu                  case 0x2:
1607119Sgblack@eecs.umich.edu                    return new QsaxReg(machInst, rd, rn, rm, 0, LSL);
1617119Sgblack@eecs.umich.edu                  case 0x3:
1627119Sgblack@eecs.umich.edu                    return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL);
1637119Sgblack@eecs.umich.edu                  case 0x4:
1647119Sgblack@eecs.umich.edu                    return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL);
1657119Sgblack@eecs.umich.edu                  case 0x7:
1667119Sgblack@eecs.umich.edu                    return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL);
1677119Sgblack@eecs.umich.edu                }
1687119Sgblack@eecs.umich.edu                break;
1697119Sgblack@eecs.umich.edu              case 0x3:
1707119Sgblack@eecs.umich.edu                switch (op2) {
1717119Sgblack@eecs.umich.edu                  case 0x0:
1727119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("shadd16", machInst);
1737119Sgblack@eecs.umich.edu                  case 0x1:
1747119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("shasx", machInst);
1757119Sgblack@eecs.umich.edu                  case 0x2:
1767119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("shsax", machInst);
1777119Sgblack@eecs.umich.edu                  case 0x3:
1787119Sgblack@eecs.umich.edu                    return new WarnUnimplemented("shsub16", machInst);
1797119Sgblack@eecs.umich.edu                  case 0x4:
1807119Sgblack@eecs.umich.edu                    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 Thumb16ShiftAddSubMoveCmp() {{
345    decode_block = '''
346    {
347        const uint32_t imm5 = bits(machInst, 10, 6);
348        const uint32_t imm3 = bits(machInst, 8, 6);
349        const uint32_t imm8 = bits(machInst, 7, 0);
350        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
351        const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
352        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
353        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6);
354        switch (bits(machInst, 13, 11)) {
355          case 0x0: // lsl
356            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL);
357          case 0x1: // lsr
358            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR);
359          case 0x2: // asr
360            return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR);
361          case 0x3:
362            switch (bits(machInst, 10, 9)) {
363              case 0x0:
364                return new AddRegCc(machInst, rd, rn, rm, 0, LSL);
365              case 0x1:
366                return new SubRegCc(machInst, rd, rn, rm, 0, LSL);
367              case 0x2:
368                return new AddImmCc(machInst, rd, rn, imm3, true);
369              case 0x3:
370                return new SubImmCc(machInst, rd, rn, imm3, true);
371            }
372          case 0x4:
373            return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false);
374          case 0x5:
375            return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true);
376          case 0x6:
377            return new AddImmCc(machInst, rd8, rd8, imm8, true);
378          case 0x7:
379            return new SubImmCc(machInst, rd8, rd8, imm8, true);
380        }
381    }
382    '''
383}};
384
385def format Thumb16DataProcessing() {{
386    decode_block = '''
387    {
388        const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0);
389        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3);
390        switch (bits(machInst, 9, 6)) {
391          case 0x0:
392            return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL);
393          case 0x1:
394            return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL);
395          case 0x2: //lsl
396            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL);
397          case 0x3: //lsr
398            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR);
399          case 0x4: //asr
400            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR);
401          case 0x5:
402            return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL);
403          case 0x6:
404            return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL);
405          case 0x7: // ror
406            return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR);
407          case 0x8:
408            return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
409          case 0x9:
410            return new RsbImmCc(machInst, rdn, rm, 0, true);
411          case 0xa:
412            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
413          case 0xb:
414            return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
415          case 0xc:
416            return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL);
417          case 0xd:
418            return new MulCc(machInst, rdn, rm, rdn);
419          case 0xe:
420            return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL);
421          case 0xf:
422            return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
423        }
424    }
425    '''
426}};
427
428def format Thumb16SpecDataAndBx() {{
429    decode_block = '''
430    {
431        const IntRegIndex rdn =
432            (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) |
433                                    (bits(machInst, 7) << 3));
434        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3);
435        switch (bits(machInst, 9, 8)) {
436          case 0x0:
437            return new AddReg(machInst, rdn, rdn, rm, 0, LSL);
438          case 0x1:
439            return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL);
440          case 0x2:
441            return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL);
442          case 0x3:
443            if (bits(machInst, 7) == 0) {
444                return new BxReg(machInst,
445                                 (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
446                                 COND_UC);
447            } else {
448                return new BlxReg(machInst,
449                                  (IntRegIndex)(uint32_t)bits(machInst, 6, 3),
450                                  COND_UC);
451            }
452        }
453    }
454    '''
455}};
456
457def format Thumb16Adr() {{
458    decode_block = '''
459    {
460        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
461        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
462        return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false);
463    }
464    '''
465}};
466
467def format Thumb16AddSp() {{
468    decode_block = '''
469    {
470        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8);
471        const uint32_t imm8 = bits(machInst, 7, 0) << 2;
472        return new AddImm(machInst, rd, INTREG_SP, imm8, true);
473    }
474    '''
475}};
476
477def format Thumb16Misc() {{
478    decode_block = '''
479    {
480        switch (bits(machInst, 11, 8)) {
481          case 0x0:
482            if (bits(machInst, 7)) {
483                return new SubImm(machInst, INTREG_SP, INTREG_SP,
484                                   bits(machInst, 6, 0) << 2, true);
485            } else {
486                return new AddImm(machInst, INTREG_SP, INTREG_SP,
487                                   bits(machInst, 6, 0) << 2, true);
488            }
489          case 0x1:
490            return new Cbz(machInst,
491                           (bits(machInst, 9) << 6) |
492                           (bits(machInst, 7, 3) << 1),
493                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
494          case 0x2:
495            switch (bits(machInst, 7, 6)) {
496              case 0x0:
497                return new WarnUnimplemented("sxth", machInst);
498              case 0x1:
499                return new WarnUnimplemented("sxtb", machInst);
500              case 0x2:
501                return new WarnUnimplemented("uxth", machInst);
502              case 0x3:
503                return new WarnUnimplemented("uxtb", machInst);
504            }
505          case 0x3:
506            return new Cbz(machInst,
507                           (bits(machInst, 9) << 6) |
508                           (bits(machInst, 7, 3) << 1),
509                           (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
510          case 0x4:
511          case 0x5:
512            return new WarnUnimplemented("push", machInst);
513          case 0x6:
514            {
515                const uint32_t opBits = bits(machInst, 7, 5);
516                if (opBits == 2) {
517                    return new WarnUnimplemented("setend", machInst);
518                } else if (opBits == 3) {
519                    return new WarnUnimplemented("cps", machInst);
520                }
521            }
522          case 0x9:
523            return new Cbnz(machInst,
524                            (bits(machInst, 9) << 6) |
525                            (bits(machInst, 7, 3) << 1),
526                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
527          case 0xa:
528            switch (bits(machInst, 7, 5)) {
529              case 0x0:
530                return new WarnUnimplemented("rev", machInst);
531              case 0x1:
532                return new WarnUnimplemented("rev16", machInst);
533              case 0x3:
534                return new WarnUnimplemented("revsh", machInst);
535              default:
536                break;
537            }
538            break;
539          case 0xb:
540            return new Cbnz(machInst,
541                            (bits(machInst, 9) << 6) |
542                            (bits(machInst, 7, 3) << 1),
543                            (IntRegIndex)(uint32_t)bits(machInst, 2, 0));
544          case 0xc:
545          case 0xd:
546            return new WarnUnimplemented("pop", machInst);
547          case 0xe:
548            return new WarnUnimplemented("bkpt", machInst);
549          case 0xf:
550            if (bits(machInst, 3, 0) != 0)
551                return new WarnUnimplemented("it", machInst);
552            switch (bits(machInst, 7, 4)) {
553              case 0x0:
554                return new WarnUnimplemented("nop", machInst);
555              case 0x1:
556                return new WarnUnimplemented("yield", machInst);
557              case 0x2:
558                return new WarnUnimplemented("wfe", machInst);
559              case 0x3:
560                return new WarnUnimplemented("wfi", machInst);
561              case 0x4:
562                return new WarnUnimplemented("sev", machInst);
563              default:
564                return new WarnUnimplemented("unallocated_hint", machInst);
565            }
566          default:
567            break;
568        }
569        return new Unknown(machInst);
570    }
571    '''
572}};
573
574def format Thumb32DataProcModImm() {{
575
576    def decInst(mnem, dest="rd", op1="rn"):
577        return '''
578            if (s) {
579                return new %(mnem)sImmCc(machInst, %(dest)s,
580                                          %(op1)s, imm, rotC);
581            } else {
582                return new %(mnem)sImm(machInst, %(dest)s,
583                                        %(op1)s, imm, rotC);
584            }
585        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
586
587    decode_block = '''
588    {
589        const uint32_t op = bits(machInst, 24, 21);
590        const bool s = (bits(machInst, 20) == 1);
591        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
592        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
593        const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 |
594                                 bits(machInst, 14, 12);
595        const bool rotC = ctrlImm > 3;
596        const uint32_t dataImm = bits(machInst, 7, 0);
597        const uint32_t imm = modified_imm(ctrlImm, dataImm);
598        switch (op) {
599          case 0x0:
600            if (rd == INTREG_PC) {
601                %(tst)s
602            } else {
603                %(and)s
604            }
605          case 0x1:
606            %(bic)s
607          case 0x2:
608            if (rn == INTREG_PC) {
609                %(mov)s
610            } else {
611                %(orr)s
612            }
613          case 0x3:
614            if (rn == INTREG_PC) {
615                %(mvn)s
616            } else {
617                %(orn)s
618            }
619          case 0x4:
620            if (rd == INTREG_PC) {
621                %(teq)s
622            } else {
623                %(eor)s
624            }
625          case 0x8:
626            if (rd == INTREG_PC) {
627                %(cmn)s
628            } else {
629                %(add)s
630            }
631          case 0xa:
632            %(adc)s
633          case 0xb:
634            %(sbc)s
635          case 0xd:
636            if (rd == INTREG_PC) {
637                %(cmp)s
638            } else {
639                %(sub)s
640            }
641          case 0xe:
642            %(rsb)s
643          default:
644            return new Unknown(machInst);
645        }
646    }
647    ''' % {
648        "tst" : decInst("Tst", "INTREG_ZERO"),
649        "and" : decInst("And"),
650        "bic" : decInst("Bic"),
651        "mov" : decInst("Mov", op1="INTREG_ZERO"),
652        "orr" : decInst("Orr"),
653        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
654        "orn" : decInst("Orn"),
655        "teq" : decInst("Teq", dest="INTREG_ZERO"),
656        "eor" : decInst("Eor"),
657        "cmn" : decInst("Cmn", dest="INTREG_ZERO"),
658        "add" : decInst("Add"),
659        "adc" : decInst("Adc"),
660        "sbc" : decInst("Sbc"),
661        "cmp" : decInst("Cmp", dest="INTREG_ZERO"),
662        "sub" : decInst("Sub"),
663        "rsb" : decInst("Rsb")
664    }
665}};
666
667def format Thumb32DataProcPlainBin() {{
668    decode_block = '''
669    {
670        const uint32_t op = bits(machInst, 24, 20);
671        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
672        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
673        switch (op) {
674          case 0x0:
675            {
676                const uint32_t imm = bits(machInst, 7, 0) |
677                                     (bits(machInst, 14, 12) << 8) |
678                                     (bits(machInst, 26) << 11);
679                if (rn == 0xf) {
680                    return new AdrImm(machInst, rd, (IntRegIndex)1,
681                                      imm, false);
682                } else {
683                    return new AddImm(machInst, rd, rn, imm, true);
684                }
685            }
686          case 0x4:
687            {
688                const uint32_t imm = bits(machInst, 7, 0) |
689                                     (bits(machInst, 14, 12) << 8) |
690                                     (bits(machInst, 26) << 11) |
691                                     (bits(machInst, 19, 16) << 12);
692                return new MovImm(machInst, rd, INTREG_ZERO, imm, true);
693            }
694          case 0xa:
695            {
696                const uint32_t imm = bits(machInst, 7, 0) |
697                                     (bits(machInst, 14, 12) << 8) |
698                                     (bits(machInst, 26) << 11);
699                if (rn == 0xf) {
700                    return new AdrImm(machInst, rd, (IntRegIndex)0,
701                                      imm, false);
702                } else {
703                    return new SubImm(machInst, rd, rn, imm, true);
704                }
705            }
706          case 0xc:
707            {
708                const uint32_t imm = bits(machInst, 7, 0) |
709                                     (bits(machInst, 14, 12) << 8) |
710                                     (bits(machInst, 26) << 11) |
711                                     (bits(machInst, 19, 16) << 12);
712                return new MovtImm(machInst, rd, rd, imm, true);
713            }
714          case 0x12:
715            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
716                return new WarnUnimplemented("ssat16", machInst);
717            }
718            // Fall through on purpose...
719          case 0x10:
720            return new WarnUnimplemented("ssat", machInst);
721          case 0x14:
722            return new WarnUnimplemented("sbfx", machInst);
723          case 0x16:
724            if (rn == 0xf) {
725                return new WarnUnimplemented("bfc", machInst);
726            } else {
727                return new WarnUnimplemented("bfi", machInst);
728            }
729          case 0x1a:
730            if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) {
731                return new WarnUnimplemented("usat16", machInst);
732            }
733            // Fall through on purpose...
734          case 0x18:
735            return new WarnUnimplemented("usat", machInst);
736          case 0x1c:
737            return new WarnUnimplemented("ubfx", machInst);
738          default:
739            return new Unknown(machInst);
740        }
741    }
742    '''
743}};
744
745def format Thumb32DataProcShiftReg() {{
746
747    def decInst(mnem, dest="rd", op1="rn"):
748        return '''
749            if (s) {
750                return new %(mnem)sRegCc(machInst, %(dest)s,
751                                          %(op1)s, rm, amt, type);
752            } else {
753                return new %(mnem)sReg(machInst, %(dest)s,
754                                        %(op1)s, rm, amt, type);
755            }
756        ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1}
757
758    decode_block = '''
759    {
760        const uint32_t op = bits(machInst, 24, 21);
761        const bool s = (bits(machInst, 20) == 1);
762        const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
763        const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8);
764        const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
765        const uint32_t amt = (bits(machInst, 14, 12) << 2) |
766                              bits(machInst, 7, 6);
767        const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4);
768        switch (op) {
769          case 0x0:
770            if (rd == INTREG_PC) {
771                %(tst)s
772            } else {
773                %(and)s
774            }
775          case 0x1:
776            %(bic)s
777          case 0x2:
778            if (rn == INTREG_PC) {
779                %(mov)s
780            } else {
781                %(orr)s
782            }
783          case 0x3:
784            if (rn == INTREG_PC) {
785                %(mvn)s
786            } else {
787                %(orn)s
788            }
789          case 0x4:
790            if (rd == INTREG_PC) {
791                %(teq)s
792            } else {
793                %(eor)s
794            }
795          case 0x6:
796            return new WarnUnimplemented("pkh", machInst);
797          case 0x8:
798            if (rd == INTREG_PC) {
799                %(cmn)s
800            } else {
801                %(add)s
802            }
803          case 0xa:
804            %(adc)s
805          case 0xb:
806            %(sbc)s
807          case 0xd:
808            if (rd == INTREG_PC) {
809                %(cmp)s
810            } else {
811                %(sub)s
812            }
813          case 0xe:
814            %(rsb)s
815          default:
816            return new Unknown(machInst);
817        }
818    }
819    ''' % {
820        "tst" : decInst("Tst", "INTREG_ZERO"),
821        "and" : decInst("And"),
822        "bic" : decInst("Bic"),
823        "mov" : decInst("Mov", op1="INTREG_ZERO"),
824        "orr" : decInst("Orr"),
825        "mvn" : decInst("Mvn", op1="INTREG_ZERO"),
826        "orn" : decInst("Orn"),
827        "teq" : decInst("Teq", "INTREG_ZERO"),
828        "eor" : decInst("Eor"),
829        "cmn" : decInst("Cmn", "INTREG_ZERO"),
830        "add" : decInst("Add"),
831        "adc" : decInst("Adc"),
832        "sbc" : decInst("Sbc"),
833        "cmp" : decInst("Cmp", "INTREG_ZERO"),
834        "sub" : decInst("Sub"),
835        "rsb" : decInst("Rsb")
836    }
837}};
838