// Copyright (c) 2010,2017 ARM Limited // All rights reserved // // The license below extends only to copyright in the software and shall // not be construed as granting a license to any other intellectual // property including but not limited to intellectual property relating // to a hardware implementation of the functionality of the software // licensed hereunder. You may use the software subject to the license // terms below provided that you ensure that this notice is replicated // unmodified and in its entirety in all distributions of the software, // modified or unmodified, in source code or in binary form. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer; // redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution; // neither the name of the copyright holders nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Authors: Gabe Black def format ArmMiscMedia() {{ decode_block = ''' { const uint32_t op1 = bits(machInst, 22, 20); const uint32_t op2 = bits(machInst, 7, 5); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex ra = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); if (op1 == 0 && op2 == 0) { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); if (ra == 0xf) { return new Usad8(machInst, rd, rn, rm); } else { return new Usada8(machInst, rd, rn, rm, ra); } } else if (bits(op2, 1, 0) == 0x2) { const uint32_t lsb = bits(machInst, 11, 7); const uint32_t msb = lsb + bits(machInst, 20, 16); if (bits(op1, 2, 1) == 0x3) { return new Ubfx(machInst, ra, rn, lsb, msb); } else if (bits(op1, 2, 1) == 0x1) { return new Sbfx(machInst, ra, rn, lsb, msb); } } else if (bits(op2, 1, 0) == 0x0 && bits(op1, 2, 1) == 0x2) { const uint32_t lsb = bits(machInst, 11, 7); const uint32_t msb = bits(machInst, 20, 16); if (rn == 0xf) { return new Bfc(machInst, ra, ra, lsb, msb); } else { return new Bfi(machInst, ra, rn, lsb, msb); } } return new Unknown(machInst); } ''' }}; def format ArmDataProcReg() {{ pclr = ''' return new %(className)ssRegPclr(machInst, %(dest)s, %(op1)s, rm, imm5, type); ''' instDecode = ''' case %(opcode)#x: if (immShift) { if (setCc) { if (%(dest)s == INTREG_PC) { %(pclr)s } else { return new %(className)sRegCc(machInst, %(dest)s, %(op1)s, rm, imm5, type); } } else { return new %(className)sReg(machInst, %(dest)s, %(op1)s, rm, imm5, type); } } else { if (setCc) { return new %(className)sRegRegCc(machInst, %(dest)s, %(op1)s, rm, rs, type); } else { return new %(className)sRegReg(machInst, %(dest)s, %(op1)s, rm, rs, type); } } break; ''' def instCode(opcode, mnem, useDest = True, useOp1 = True): global pclr if useDest: dest = "rd" else: dest = "INTREG_ZERO" if useOp1: op1 = "rn" else: op1 = "INTREG_ZERO" global instDecode, pclrCode substDict = { "className": mnem.capitalize(), "opcode": opcode, "dest": dest, "op1": op1 } if useDest: substDict["pclr"] = pclr % substDict else: substDict["pclr"] = "" return instDecode % substDict decode_block = ''' { const bool immShift = (bits(machInst, 4) == 0); const bool setCc = (bits(machInst, 20) == 1); const uint32_t imm5 = bits(machInst, 11, 7); const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5); const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; const IntRegIndex rm = (IntRegIndex)(uint32_t)RM; const IntRegIndex rs = (IntRegIndex)(uint32_t)RS; switch (OPCODE) { ''' decode_block += instCode(0x0, "and") decode_block += instCode(0x1, "eor") decode_block += instCode(0x2, "sub") decode_block += instCode(0x3, "rsb") decode_block += instCode(0x4, "add") decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") decode_block += instCode(0x8, "tst", useDest = False) decode_block += instCode(0x9, "teq", useDest = False) decode_block += instCode(0xa, "cmp", useDest = False) decode_block += instCode(0xb, "cmn", useDest = False) decode_block += instCode(0xc, "orr") decode_block += instCode(0xd, "mov", useOp1 = False) decode_block += instCode(0xe, "bic") decode_block += instCode(0xf, "mvn", useOp1 = False) decode_block += ''' default: return new Unknown(machInst); } } ''' }}; def format ArmPackUnpackSatReverse() {{ decode_block = ''' { const uint32_t op1 = bits(machInst, 22, 20); const uint32_t a = bits(machInst, 19, 16); const uint32_t op2 = bits(machInst, 7, 5); if (bits(op2, 0) == 0) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const uint32_t satImm = bits(machInst, 20, 16); const uint32_t imm = bits(machInst, 11, 7); const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 6, 5); if (op1 == 0) { if (type) { return new PkhtbReg(machInst, rd, (IntRegIndex)a, rn, imm, type); } else { return new PkhbtReg(machInst, rd, (IntRegIndex)a, rn, imm, type); } } else if (bits(op1, 2, 1) == 1) { return new Ssat(machInst, rd, satImm + 1, rn, imm, type); } else if (bits(op1, 2, 1) == 3) { return new Usat(machInst, rd, satImm, rn, imm, type); } return new Unknown(machInst); } switch (op1) { case 0x0: { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); if (op2 == 0x3) { const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Sxtb16(machInst, rd, rotation, rm); } else { return new Sxtab16(machInst, rd, rn, rm, rotation); } } else if (op2 == 0x5) { return new Sel(machInst, rd, rn, rm); } } break; case 0x2: if (op2 == 0x1) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const uint32_t satImm = bits(machInst, 20, 16); return new Ssat16(machInst, rd, satImm + 1, rn); } else if (op2 == 0x3) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Sxtb(machInst, rd, rotation, rm); } else { return new Sxtab(machInst, rd, rn, rm, rotation); } } break; case 0x3: if (op2 == 0x1) { IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); return new Rev(machInst, rd, rm); } else if (op2 == 0x3) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Sxth(machInst, rd, rotation, rm); } else { return new Sxtah(machInst, rd, rn, rm, rotation); } } else if (op2 == 0x5) { IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); return new Rev16(machInst, rd, rm); } break; case 0x4: if (op2 == 0x3) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Uxtb16(machInst, rd, rotation, rm); } else { return new Uxtab16(machInst, rd, rn, rm, rotation); } } break; case 0x6: if (op2 == 0x1) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const uint32_t satImm = bits(machInst, 20, 16); return new Usat16(machInst, rd, satImm, rn); } else if (op2 == 0x3) { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Uxtb(machInst, rd, rotation, rm); } else { return new Uxtab(machInst, rd, rn, rm, rotation); } } break; case 0x7: { const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); if (op2 == 0x1) { return new Rbit(machInst, rd, rm); } else if (op2 == 0x3) { const uint32_t rotation = (uint32_t)bits(machInst, 11, 10) << 3; if (a == 0xf) { return new Uxth(machInst, rd, rotation, rm); } else { return new Uxtah(machInst, rd, rn, rm, rotation); } } else if (op2 == 0x5) { return new Revsh(machInst, rd, rm); } } break; } return new Unknown(machInst); } ''' }}; def format ArmParallelAddSubtract() {{ decode_block=''' { const uint32_t op1 = bits(machInst, 21, 20); const uint32_t op2 = bits(machInst, 7, 5); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); if (bits(machInst, 22) == 0) { switch (op1) { case 0x1: switch (op2) { case 0x0: return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x1: return new SasxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x2: return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL); } break; case 0x2: switch (op2) { case 0x0: return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x1: return new QasxReg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new QsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; case 0x3: switch (op2) { case 0x0: return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x1: return new ShasxReg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; } } else { switch (op1) { case 0x1: switch (op2) { case 0x0: return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x1: return new UasxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL); } break; case 0x2: switch (op2) { case 0x0: return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x1: return new UqasxReg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; case 0x3: switch (op2) { case 0x0: return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x1: return new UhasxReg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x3: return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x7: return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; } } return new Unknown(machInst); } ''' }}; def format ArmDataProcImm() {{ pclr = ''' return new %(className)ssImmPclr(machInst, %(dest)s, %(op1)s, imm, false); ''' adr = ''' return new AdrImm(machInst, %(dest)s, %(add)s, imm, false); ''' instDecode = ''' case %(opcode)#x: if (setCc) { if (%(pclrInst)s && %(dest)s == INTREG_PC) { %(pclr)s } else { return new %(className)sImmCc(machInst, %(dest)s, %(op1)s, imm, rotC); } } else { if (%(adrInst)s && %(op1)s == INTREG_PC) { %(adr)s } else { return new %(className)sImm(machInst, %(dest)s, %(op1)s, imm, rotC); } } break; ''' def instCode(opcode, mnem, useDest = True, useOp1 = True): global instDecode, pclr, adr if useDest: dest = "rd" else: dest = "INTREG_ZERO" if useOp1: op1 = "rn" else: op1 = "INTREG_ZERO" substDict = { "className": mnem.capitalize(), "opcode": opcode, "dest": dest, "op1": op1, "adr": "", "adrInst": "false" } if useDest: substDict["pclrInst"] = "true" substDict["pclr"] = pclr % substDict else: substDict["pclrInst"] = "false" substDict["pclr"] = "" return instDecode % substDict def adrCode(opcode, mnem, add="1"): global instDecode, pclr, adr substDict = { "className": mnem.capitalize(), "opcode": opcode, "dest": "rd", "op1": "rn", "add": add, "pclrInst": "true", "adrInst": "true" } substDict["pclr"] = pclr % substDict substDict["adr"] = adr % substDict return instDecode % substDict decode_block = ''' { const bool setCc = (bits(machInst, 20) == 1); const uint32_t unrotated = bits(machInst, 7, 0); const uint32_t rotation = (bits(machInst, 11, 8) << 1); const bool rotC = (rotation != 0); const uint32_t imm = rotate_imm(unrotated, rotation); const IntRegIndex rd = (IntRegIndex)(uint32_t)RD; const IntRegIndex rn = (IntRegIndex)(uint32_t)RN; switch (OPCODE) { ''' decode_block += instCode(0x0, "and") decode_block += instCode(0x1, "eor") decode_block += adrCode(0x2, "sub", add="(IntRegIndex)0") decode_block += instCode(0x3, "rsb") decode_block += adrCode(0x4, "add", add="(IntRegIndex)1") decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") decode_block += instCode(0x8, "tst", useDest = False) decode_block += instCode(0x9, "teq", useDest = False) decode_block += instCode(0xa, "cmp", useDest = False) decode_block += instCode(0xb, "cmn", useDest = False) decode_block += instCode(0xc, "orr") decode_block += instCode(0xd, "mov", useOp1 = False) decode_block += instCode(0xe, "bic") decode_block += instCode(0xf, "mvn", useOp1 = False) decode_block += ''' default: return new Unknown(machInst); } } ''' }}; def format ArmSatAddSub() {{ decode_block = ''' { IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12); IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); switch (OPCODE) { case 0x8: return new QaddRegCc(machInst, rd, rm, rn, 0, LSL); case 0x9: return new QsubRegCc(machInst, rd, rm, rn, 0, LSL); case 0xa: return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL); case 0xb: return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL); default: return new Unknown(machInst); } } ''' }}; def format Thumb32DataProcReg() {{ decode_block = ''' { const uint32_t op1 = bits(machInst, 23, 20); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const uint32_t op2 = bits(machInst, 7, 4); if (bits(machInst, 15, 12) != 0xf) { return new Unknown(machInst); } if (bits(op1, 3) != 1) { if (op2 == 0) { IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); switch (bits(op1, 2, 0)) { case 0x0: return new MovRegReg(machInst, rd, INTREG_ZERO, rn, rm, LSL); case 0x1: return new MovRegRegCc(machInst, rd, INTREG_ZERO, rn, rm, LSL); case 0x2: return new MovRegReg(machInst, rd, INTREG_ZERO, rn, rm, LSR); case 0x3: return new MovRegRegCc(machInst, rd, INTREG_ZERO, rn, rm, LSR); case 0x4: return new MovRegReg(machInst, rd, INTREG_ZERO, rn, rm, ASR); case 0x5: return new MovRegRegCc(machInst, rd, INTREG_ZERO, rn, rm, ASR); case 0x6: return new MovRegReg(machInst, rd, INTREG_ZERO, rn, rm, ROR); case 0x7: return new MovRegRegCc(machInst, rd, INTREG_ZERO, rn, rm, ROR); } } else if (bits(op2, 3) == 0) { return new Unknown(machInst); } else { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t rotation = (uint32_t)bits(machInst, 5, 4) << 3; switch (bits(op1, 2, 0)) { case 0x0: if (rn == 0xf) { return new Sxth(machInst, rd, rotation, rm); } else { return new Sxtah(machInst, rd, rn, rm, rotation); } case 0x1: if (rn == 0xf) { return new Uxth(machInst, rd, rotation, rm); } else { return new Uxtah(machInst, rd, rn, rm, rotation); } case 0x2: if (rn == 0xf) { return new Sxtb16(machInst, rd, rotation, rm); } else { return new Sxtab16(machInst, rd, rn, rm, rotation); } case 0x3: if (rn == 0xf) { return new Uxtb16(machInst, rd, rotation, rm); } else { return new Uxtab16(machInst, rd, rn, rm, rotation); } case 0x4: if (rn == 0xf) { return new Sxtb(machInst, rd, rotation, rm); } else { return new Sxtab(machInst, rd, rn, rm, rotation); } case 0x5: if (rn == 0xf) { return new Uxtb(machInst, rd, rotation, rm); } else { return new Uxtab(machInst, rd, rn, rm, rotation); } default: return new Unknown(machInst); } } } else { if (bits(op2, 3) == 0) { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); if (bits(op2, 2) == 0x0) { const uint32_t op1 = bits(machInst, 22, 20); const uint32_t op2 = bits(machInst, 5, 4); switch (op2) { case 0x0: switch (op1) { case 0x1: return new Sadd16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x2: return new SasxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x6: return new SsaxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Ssub16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Sadd8RegCc(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Ssub8RegCc(machInst, rd, rn, rm, 0, LSL); } break; case 0x1: switch (op1) { case 0x1: return new Qadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new QasxReg(machInst, rd, rn, rm, 0, LSL); case 0x6: return new QsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Qsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Qadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Qsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; case 0x2: switch (op1) { case 0x1: return new Shadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new ShasxReg(machInst, rd, rn, rm, 0, LSL); case 0x6: return new ShsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Shsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Shadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Shsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; } } else { const uint32_t op1 = bits(machInst, 22, 20); const uint32_t op2 = bits(machInst, 5, 4); switch (op2) { case 0x0: switch (op1) { case 0x1: return new Uadd16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UasxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x6: return new UsaxRegCc(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Usub16RegCc(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Uadd8RegCc(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Usub8RegCc(machInst, rd, rn, rm, 0, LSL); } break; case 0x1: switch (op1) { case 0x1: return new Uqadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UqasxReg(machInst, rd, rn, rm, 0, LSL); case 0x6: return new UqsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Uqsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Uqadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Uqsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; case 0x2: switch (op1) { case 0x1: return new Uhadd16Reg(machInst, rd, rn, rm, 0, LSL); case 0x2: return new UhasxReg(machInst, rd, rn, rm, 0, LSL); case 0x6: return new UhsaxReg(machInst, rd, rn, rm, 0, LSL); case 0x5: return new Uhsub16Reg(machInst, rd, rn, rm, 0, LSL); case 0x0: return new Uhadd8Reg(machInst, rd, rn, rm, 0, LSL); case 0x4: return new Uhsub8Reg(machInst, rd, rn, rm, 0, LSL); } break; } } } else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) { const uint32_t op1 = bits(machInst, 22, 20); const uint32_t op2 = bits(machInst, 5, 4); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); switch (op1) { case 0x0: switch (op2) { case 0x0: return new QaddRegCc(machInst, rd, rm, rn, 0, LSL); case 0x1: return new QdaddRegCc(machInst, rd, rm, rn, 0, LSL); case 0x2: return new QsubRegCc(machInst, rd, rm, rn, 0, LSL); case 0x3: return new QdsubRegCc(machInst, rd, rm, rn, 0, LSL); } break; case 0x1: switch (op2) { case 0x0: return new Rev(machInst, rd, rn); case 0x1: return new Rev16(machInst, rd, rn); case 0x2: return new Rbit(machInst, rd, rm); case 0x3: return new Revsh(machInst, rd, rn); } break; case 0x2: if (op2 == 0) { return new Sel(machInst, rd, rn, rm); } break; case 0x3: if (op2 == 0) { return new Clz(machInst, rd, rm); } break; case 0x4: switch (op2) { case 0x0: return new Crc32b(machInst, rd, rn, rm); case 0x1: return new Crc32h(machInst, rd, rn, rm); case 0x2: return new Crc32w(machInst, rd, rn, rm); } break; case 0x5: switch (op2) { case 0x0: return new Crc32cb(machInst, rd, rn, rm); case 0x1: return new Crc32ch(machInst, rd, rn, rm); case 0x2: return new Crc32cw(machInst, rd, rn, rm); } break; } } return new Unknown(machInst); } } ''' }}; def format Thumb16ShiftAddSubMoveCmp() {{ decode_block = ''' { const uint32_t imm5 = bits(machInst, 10, 6); const uint32_t imm3 = bits(machInst, 8, 6); const uint32_t imm8 = bits(machInst, 7, 0); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); const IntRegIndex rd8 = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 8, 6); switch (bits(machInst, 13, 11)) { case 0x0: // lsl if (machInst.itstateMask) { return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL); } else { return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSL); } case 0x1: // lsr if (machInst.itstateMask) { return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR); } else { return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, LSR); } case 0x2: // asr if (machInst.itstateMask) { return new MovReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR); } else { return new MovRegCc(machInst, rd, INTREG_ZERO, rn, imm5, ASR); } case 0x3: switch (bits(machInst, 10, 9)) { case 0x0: if (machInst.itstateMask) { return new AddReg(machInst, rd, rn, rm, 0, LSL); } else { return new AddRegCc(machInst, rd, rn, rm, 0, LSL); } case 0x1: if (machInst.itstateMask) { return new SubReg(machInst, rd, rn, rm, 0, LSL); } else { return new SubRegCc(machInst, rd, rn, rm, 0, LSL); } case 0x2: if (machInst.itstateMask) { return new AddImm(machInst, rd, rn, imm3, true); } else { return new AddImmCc(machInst, rd, rn, imm3, true); } case 0x3: if (machInst.itstateMask) { return new SubImm(machInst, rd, rn, imm3, true); } else { return new SubImmCc(machInst, rd, rn, imm3, true); } } case 0x4: if (machInst.itstateMask) { return new MovImm(machInst, rd8, INTREG_ZERO, imm8, false); } else { return new MovImmCc(machInst, rd8, INTREG_ZERO, imm8, false); } case 0x5: return new CmpImmCc(machInst, INTREG_ZERO, rd8, imm8, true); case 0x6: if (machInst.itstateMask) { return new AddImm(machInst, rd8, rd8, imm8, true); } else { return new AddImmCc(machInst, rd8, rd8, imm8, true); } case 0x7: if (machInst.itstateMask) { return new SubImm(machInst, rd8, rd8, imm8, true); } else { return new SubImmCc(machInst, rd8, rd8, imm8, true); } } } ''' }}; def format Thumb16DataProcessing() {{ decode_block = ''' { const IntRegIndex rdn = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); switch (bits(machInst, 9, 6)) { case 0x0: if (machInst.itstateMask) { return new AndReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new AndRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0x1: if (machInst.itstateMask) { return new EorReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new EorRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0x2: //lsl if (machInst.itstateMask) { return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSL); } else { return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSL); } case 0x3: //lsr if (machInst.itstateMask) { return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSR); } else { return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, LSR); } case 0x4: //asr if (machInst.itstateMask) { return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ASR); } else { return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ASR); } case 0x5: if (machInst.itstateMask) { return new AdcReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new AdcRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0x6: if (machInst.itstateMask) { return new SbcReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new SbcRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0x7: // ror if (machInst.itstateMask) { return new MovRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ROR); } else { return new MovRegRegCc(machInst, rdn, INTREG_ZERO, rdn, rm, ROR); } case 0x8: return new TstRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); case 0x9: if (machInst.itstateMask) { return new RsbImm(machInst, rdn, rm, 0, true); } else { return new RsbImmCc(machInst, rdn, rm, 0, true); } case 0xa: return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); case 0xb: return new CmnRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); case 0xc: if (machInst.itstateMask) { return new OrrReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new OrrRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0xd: if (machInst.itstateMask) { return new Mul(machInst, rdn, rm, rdn); } else { return new MulCc(machInst, rdn, rm, rdn); } case 0xe: if (machInst.itstateMask) { return new BicReg(machInst, rdn, rdn, rm, 0, LSL); } else { return new BicRegCc(machInst, rdn, rdn, rm, 0, LSL); } case 0xf: if (machInst.itstateMask) { return new MvnReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); } else { return new MvnRegCc(machInst, rdn, INTREG_ZERO, rm, 0, LSL); } } } ''' }}; def format Thumb16SpecDataAndBx() {{ decode_block = ''' { const IntRegIndex rdn = (IntRegIndex)(uint32_t)(bits(machInst, 2, 0) | (bits(machInst, 7) << 3)); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 6, 3); switch (bits(machInst, 9, 8)) { case 0x0: return new AddReg(machInst, rdn, rdn, rm, 0, LSL); case 0x1: return new CmpRegCc(machInst, INTREG_ZERO, rdn, rm, 0, LSL); case 0x2: return new MovReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); case 0x3: if (bits(machInst, 7) == 0) { return new BxReg(machInst, (IntRegIndex)(uint32_t)bits(machInst, 6, 3), COND_UC); } else { return new BlxReg(machInst, (IntRegIndex)(uint32_t)bits(machInst, 6, 3), COND_UC); } } } ''' }}; def format Thumb16Adr() {{ decode_block = ''' { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); const uint32_t imm8 = bits(machInst, 7, 0) << 2; return new AdrImm(machInst, rd, (IntRegIndex)1, imm8, false); } ''' }}; def format Thumb16AddSp() {{ decode_block = ''' { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 10, 8); const uint32_t imm8 = bits(machInst, 7, 0) << 2; return new AddImm(machInst, rd, INTREG_SP, imm8, true); } ''' }}; def format ArmMisc() {{ decode_block = ''' { const uint32_t unrotated = bits(machInst, 7, 0); const uint32_t rotation = (bits(machInst, 11, 8) << 1); const uint32_t imm = rotate_imm(unrotated, rotation); const uint8_t byteMask = bits(machInst, 19, 16); switch (OPCODE) { case 0x8: return new MovImm(machInst, (IntRegIndex)(uint32_t)RD, (IntRegIndex)INTREG_ZERO, bits(machInst, 11, 0) | (bits(machInst, 19, 16) << 12), false); case 0x9: if (RN == 0) { switch (IMM) { case 0x0: return new NopInst(machInst); case 0x1: return new YieldInst(machInst); case 0x2: return new WfeInst(machInst); case 0x3: return new WfiInst(machInst); case 0x4: return new SevInst(machInst); default: return new Unknown(machInst); } } else { return new MsrCpsrImm(machInst, imm, byteMask); } case 0xa: { const uint32_t timm = (bits(machInst, 19, 16) << 12) | bits(machInst, 11, 0); return new MovtImm(machInst, (IntRegIndex)(uint32_t)RD, (IntRegIndex)(uint32_t)RD, timm, true); } case 0xb: return new MsrSpsrImm(machInst, imm, byteMask); default: return new Unknown(machInst); } } ''' }}; def format Thumb16Misc() {{ decode_block = ''' { switch (bits(machInst, 11, 8)) { case 0x0: if (bits(machInst, 7)) { return new SubImm(machInst, INTREG_SP, INTREG_SP, bits(machInst, 6, 0) << 2, true); } else { return new AddImm(machInst, INTREG_SP, INTREG_SP, bits(machInst, 6, 0) << 2, true); } case 0x2: { const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); switch (bits(machInst, 7, 6)) { case 0x0: return new Sxth(machInst, rd, 0, rm); case 0x1: return new Sxtb(machInst, rd, 0, rm); case 0x2: return new Uxth(machInst, rd, 0, rm); case 0x3: return new Uxtb(machInst, rd, 0, rm); } } case 0x1: case 0x3: return new Cbz(machInst, (bits(machInst, 9) << 6) | (bits(machInst, 7, 3) << 1), (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); case 0x4: case 0x5: { const uint32_t m = bits(machInst, 8); const uint32_t regList = bits(machInst, 7, 0) | (m << 14); return new LdmStm(machInst, INTREG_SP, false, false, false, true, false, regList); } case 0x6: { const uint32_t opBits = bits(machInst, 7, 5); if (opBits == 2) { return new Setend(machInst, bits(machInst, 3)); } else if (opBits == 3) { const bool enable = (bits(machInst, 4) == 0); const uint32_t mods = (bits(machInst, 2, 0) << 5) | ((enable ? 1 : 0) << 9); return new Cps(machInst, mods); } } case 0xa: { IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 2, 0); IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 5, 3); switch (bits(machInst, 7, 6)) { case 0x0: return new Rev(machInst, rd, rm); case 0x1: return new Rev16(machInst, rd, rm); case 0x3: return new Revsh(machInst, rd, rm); default: break; } } break; case 0x9: case 0xb: return new Cbnz(machInst, (bits(machInst, 9) << 6) | (bits(machInst, 7, 3) << 1), (IntRegIndex)(uint32_t)bits(machInst, 2, 0)); case 0xc: case 0xd: { const uint32_t p = bits(machInst, 8); const uint32_t regList = bits(machInst, 7, 0) | (p << 15); return new LdmStm(machInst, INTREG_SP, true, true, false, true, true, regList); } case 0xe: return new BkptInst(machInst); case 0xf: if (bits(machInst, 3, 0) != 0) return new ItInst(machInst); switch (bits(machInst, 7, 4)) { case 0x0: return new NopInst(machInst); case 0x1: return new YieldInst(machInst); case 0x2: return new WfeInst(machInst); case 0x3: return new WfiInst(machInst); case 0x4: return new SevInst(machInst); default: return new WarnUnimplemented("unallocated_hint", machInst); } default: break; } return new Unknown(machInst); } ''' }}; def format Thumb32DataProcModImm() {{ def decInst(mnem, dest="rd", op1="rn"): return ''' if (s) { return new %(mnem)sImmCc(machInst, %(dest)s, %(op1)s, imm, rotC); } else { return new %(mnem)sImm(machInst, %(dest)s, %(op1)s, imm, rotC); } ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} decode_block = ''' { const uint32_t op = bits(machInst, 24, 21); const bool s = (bits(machInst, 20) == 1); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); const uint32_t ctrlImm = bits(machInst.instBits, 26) << 3 | bits(machInst, 14, 12); const bool rotC = ctrlImm > 3; const uint32_t dataImm = bits(machInst, 7, 0); const uint32_t imm = modified_imm(ctrlImm, dataImm); switch (op) { case 0x0: if (rd == INTREG_PC) { %(tst)s } else { %(and)s } case 0x1: %(bic)s case 0x2: if (rn == INTREG_PC) { %(mov)s } else { %(orr)s } case 0x3: if (rn == INTREG_PC) { %(mvn)s } else { %(orn)s } case 0x4: if (rd == INTREG_PC) { %(teq)s } else { %(eor)s } case 0x8: if (rd == INTREG_PC) { %(cmn)s } else { %(add)s } case 0xa: %(adc)s case 0xb: %(sbc)s case 0xd: if (rd == INTREG_PC) { %(cmp)s } else { %(sub)s } case 0xe: %(rsb)s default: return new Unknown(machInst); } } ''' % { "tst" : decInst("Tst", "INTREG_ZERO"), "and" : decInst("And"), "bic" : decInst("Bic"), "mov" : decInst("Mov", op1="INTREG_ZERO"), "orr" : decInst("Orr"), "mvn" : decInst("Mvn", op1="INTREG_ZERO"), "orn" : decInst("Orn"), "teq" : decInst("Teq", dest="INTREG_ZERO"), "eor" : decInst("Eor"), "cmn" : decInst("Cmn", dest="INTREG_ZERO"), "add" : decInst("Add"), "adc" : decInst("Adc"), "sbc" : decInst("Sbc"), "cmp" : decInst("Cmp", dest="INTREG_ZERO"), "sub" : decInst("Sub"), "rsb" : decInst("Rsb") } }}; def format Thumb32DataProcPlainBin() {{ decode_block = ''' { const uint32_t op = bits(machInst, 24, 20); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); switch (op) { case 0x0: { const uint32_t imm = bits(machInst, 7, 0) | (bits(machInst, 14, 12) << 8) | (bits(machInst, 26) << 11); if (rn == 0xf) { return new AdrImm(machInst, rd, (IntRegIndex)1, imm, false); } else { return new AddImm(machInst, rd, rn, imm, true); } } case 0x4: { const uint32_t imm = bits(machInst, 7, 0) | (bits(machInst, 14, 12) << 8) | (bits(machInst, 26) << 11) | (bits(machInst, 19, 16) << 12); return new MovImm(machInst, rd, INTREG_ZERO, imm, true); } case 0xa: { const uint32_t imm = bits(machInst, 7, 0) | (bits(machInst, 14, 12) << 8) | (bits(machInst, 26) << 11); if (rn == 0xf) { return new AdrImm(machInst, rd, (IntRegIndex)0, imm, false); } else { return new SubImm(machInst, rd, rn, imm, true); } } case 0xc: { const uint32_t imm = bits(machInst, 7, 0) | (bits(machInst, 14, 12) << 8) | (bits(machInst, 26) << 11) | (bits(machInst, 19, 16) << 12); return new MovtImm(machInst, rd, rd, imm, true); } case 0x12: if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { const uint32_t satImm = bits(machInst, 4, 0); return new Ssat16(machInst, rd, satImm + 1, rn); } // Fall through on purpose... case 0x10: { const uint32_t satImm = bits(machInst, 4, 0); const uint32_t imm = bits(machInst, 7, 6) | (bits(machInst, 14, 12) << 2); const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 21, 20); return new Ssat(machInst, rd, satImm + 1, rn, imm, type); } case 0x14: { const uint32_t lsb = bits(machInst, 7, 6) | (bits(machInst, 14, 12) << 2); const uint32_t msb = lsb + bits(machInst, 4, 0); return new Sbfx(machInst, rd, rn, lsb, msb); } case 0x16: { const uint32_t lsb = bits(machInst, 7, 6) | (bits(machInst, 14, 12) << 2); const uint32_t msb = bits(machInst, 4, 0); if (rn == 0xf) { return new Bfc(machInst, rd, rd, lsb, msb); } else { return new Bfi(machInst, rd, rn, lsb, msb); } } case 0x1a: if (!(bits(machInst, 14, 12) || bits(machInst, 7, 6))) { const uint32_t satImm = bits(machInst, 4, 0); return new Usat16(machInst, rd, satImm, rn); } // Fall through on purpose... case 0x18: { const uint32_t satImm = bits(machInst, 4, 0); const uint32_t imm = bits(machInst, 7, 6) | (bits(machInst, 14, 12) << 2); const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 21, 20); return new Usat(machInst, rd, satImm, rn, imm, type); } case 0x1c: { const uint32_t lsb = bits(machInst, 7, 6) | (bits(machInst, 14, 12) << 2); const uint32_t msb = lsb + bits(machInst, 4, 0); return new Ubfx(machInst, rd, rn, lsb, msb); } default: return new Unknown(machInst); } } ''' }}; def format Thumb32DataProcShiftReg() {{ def decInst(mnem, dest="rd", op1="rn"): return ''' if (s) { return new %(mnem)sRegCc(machInst, %(dest)s, %(op1)s, rm, amt, type); } else { return new %(mnem)sReg(machInst, %(dest)s, %(op1)s, rm, amt, type); } ''' % {"mnem" : mnem, "dest" : dest, "op1" : op1} decode_block = ''' { const uint32_t op = bits(machInst, 24, 21); const bool s = (bits(machInst, 20) == 1); const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16); const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 11, 8); const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0); const uint32_t amt = (bits(machInst, 14, 12) << 2) | bits(machInst, 7, 6); const ArmShiftType type = (ArmShiftType)(uint32_t)bits(machInst, 5, 4); switch (op) { case 0x0: if (rd == INTREG_PC) { %(tst)s } else { %(and)s } case 0x1: %(bic)s case 0x2: if (rn == INTREG_PC) { %(mov)s } else { %(orr)s } case 0x3: if (rn == INTREG_PC) { %(mvn)s } else { %(orn)s } case 0x4: if (rd == INTREG_PC) { %(teq)s } else { %(eor)s } case 0x6: if (type) { return new PkhtbReg(machInst, rd, rn, rm, amt, type); } else { return new PkhbtReg(machInst, rd, rn, rm, amt, type); } case 0x8: if (rd == INTREG_PC) { %(cmn)s } else { %(add)s } case 0xa: %(adc)s case 0xb: %(sbc)s case 0xd: if (rd == INTREG_PC) { %(cmp)s } else { %(sub)s } case 0xe: %(rsb)s default: return new Unknown(machInst); } } ''' % { "tst" : decInst("Tst", "INTREG_ZERO"), "and" : decInst("And"), "bic" : decInst("Bic"), "mov" : decInst("Mov", op1="INTREG_ZERO"), "orr" : decInst("Orr"), "mvn" : decInst("Mvn", op1="INTREG_ZERO"), "orn" : decInst("Orn"), "teq" : decInst("Teq", "INTREG_ZERO"), "eor" : decInst("Eor"), "cmn" : decInst("Cmn", "INTREG_ZERO"), "add" : decInst("Add"), "adc" : decInst("Adc"), "sbc" : decInst("Sbc"), "cmp" : decInst("Cmp", "INTREG_ZERO"), "sub" : decInst("Sub"), "rsb" : decInst("Rsb") } }};