diff options
Diffstat (limited to 'src/arch')
-rw-r--r-- | src/arch/arm/isa/decoder/thumb.isa | 203 | ||||
-rw-r--r-- | src/arch/arm/isa/formats/data.isa | 459 |
2 files changed, 441 insertions, 221 deletions
diff --git a/src/arch/arm/isa/decoder/thumb.isa b/src/arch/arm/isa/decoder/thumb.isa index dfaca8f42..9071649a2 100644 --- a/src/arch/arm/isa/decoder/thumb.isa +++ b/src/arch/arm/isa/decoder/thumb.isa @@ -43,98 +43,18 @@ 1: decode BIGTHUMB { // 16 bit thumb instructions. 0: decode TOPCODE_15_13 { - 0x0, 0x1: decode TOPCODE_13_11 { - 0x0: WarnUnimpl::lsl(); //immediate - 0x1: WarnUnimpl::lsr(); //immediate - 0x2: WarnUnimpl::asr(); //immediate - 0x3: decode TOPCODE_10_9 { - 0x0: WarnUnimpl::add(); //register - 0x1: WarnUnimpl::sub(); //register - 0x2: WarnUnimpl::add(); //3 bit immediate - 0x3: WarnUnimpl::sub(); //3 bit immediate - } - 0x4: WarnUnimpl::mov(); //immediate - 0x5: WarnUnimpl::cmp(); //immediate - 0x6: WarnUnimpl::add(); //8 bit immediate, thumb - 0x7: WarnUnimpl::sub(); //8 bit immediate, thumb - } + 0x0, 0x1: Thumb16ShiftAddSubMoveCmp::thumb16ShiftAddMoveCmp(); 0x2: decode TOPCODE_12_10 { - // Data processing - 0x0: decode TOPCODE_9_6 { - 0x0: WarnUnimpl::and(); //register - 0x1: WarnUnimpl::eor(); //register - 0x2: WarnUnimpl::lsl(); //register - 0x3: WarnUnimpl::lsr(); //register - 0x4: WarnUnimpl::asr(); //register - 0x5: WarnUnimpl::adc(); //register - 0x6: WarnUnimpl::sbc(); //register - 0x7: WarnUnimpl::ror(); //register - 0x8: WarnUnimpl::tst(); //register - 0x9: WarnUnimpl::rsb(); //immediate - 0xa: WarnUnimpl::cmp(); //register (high registers) - 0xb: WarnUnimpl::cmn(); //register - 0xc: WarnUnimpl::orr(); //register - 0xd: WarnUnimpl::mul(); - 0xe: WarnUnimpl::bic(); //register - 0xf: WarnUnimpl::mvn(); //register - } - // Special data instructions and branch and exchange - 0x1: decode TOPCODE_9_6 { - 0x0: WarnUnimpl::add(); //register (low registers) - 0x1, 0x2, 0x3: WarnUnimpl::add(); //register (high registers) - 0x4: WarnUnimpl::unpredictable(); //? - 0x5, 0x6, 0x7: WarnUnimpl::cmp(); //register - 0x8: WarnUnimpl::mov(); //register (low registers) - 0x9, 0xa, 0xb: WarnUnimpl::mov(); //register (high registers) - 0xc, 0xd: WarnUnimpl::bx(); - 0xe, 0xf: WarnUnimpl::blx(); //register - } + 0x0: Thumb16DataProcessing::thumb16DataProcessing(); + 0x1: Thumb16SpecDataAndBx::thumb16SpecDataAndBx(); 0x2, 0x3: Thumb16MemLit::thumb16MemLit(); default: Thumb16MemReg::thumb16MemReg(); } 0x3, 0x4: Thumb16MemImm::thumb16MemImm(); 0x5: decode TOPCODE_12_11 { - 0x0: WarnUnimpl::adr(); - 0x1: WarnUnimpl::add(); //sp, immediate - 0x2: decode TOPCODE_10_8 { - 0x0: decode TOPCODE_7 { - 0x0: WarnUnimpl::add(); //sp, immediate - 0x1: WarnUnimpl::sub(); //sp, immediate - } - 0x1, 0x3: WarnUnimpl::cbz(); //cbnz too... - 0x2: decode TOPCODE_7_6 { - 0x0: WarnUnimpl::sxth(); - 0x1: WarnUnimpl::sxtb(); - 0x2: WarnUnimpl::uxth(); - 0x3: WarnUnimpl::uxtb(); - } - 0x4, 0x5: WarnUnimpl::pop(); - 0x6: decode TOPCODE_7_5 { - 0x2: WarnUnimpl::setend(); - 0x3: WarnUnimpl::cps(); - } - } - 0x3: decode TOPCODE_10_8 { - 0x1, 0x3: WarnUnimpl::cbz(); //cbnz too... - 0x2: decode TOPCODE_7_6 { - 0x0: WarnUnimpl::rev(); - 0x1: WarnUnimpl::rev16(); - 0x3: WarnUnimpl::revsh(); - } - 0x4, 0x5: WarnUnimpl::pop(); - 0x6: WarnUnimpl::bkpt(); - 0x7: decode TOPCODE_3_0 { - 0x0: WarnUnimpl::it(); - default: decode TOPCODE_7_4 { - 0x0: WarnUnimpl::nop(); - 0x1: WarnUnimpl::yield(); - 0x2: WarnUnimpl::wfe(); - 0x3: WarnUnimpl::wfi(); - 0x4: WarnUnimpl::sev(); - default: WarnUnimpl::unallocated_hint(); - } - } - } + 0x0: Thumb16Adr::thumb16Adr(); + 0x1: Thumb16AddSp::thumb16AddSp(); //sp, immediate + 0x2, 0x3: Thumb16Misc::thumb16Misc(); } 0x6: decode TOPCODE_12_11 { 0x0, 0x1: Thumb16MacroMem::thumb16MacroMem(); @@ -197,45 +117,7 @@ } } } - 0x1: decode HTOPCODE_8_5 { - 0x0: decode LTRD { - 0xf: decode HTS { - 0x1: WarnUnimpl::tst(); // register - } - default: WarnUnimpl::and(); // register - } - 0x1: WarnUnimpl::bic(); // register - 0x2: decode HTRN { - 0xf: WarnUnimpl::mov(); // register - default: WarnUnimpl::orr(); // register - } - 0x3: decode HTRN { - 0xf: WarnUnimpl::mvn(); // register - default: WarnUnimpl::orn(); // register - } - 0x4: decode LTRD { - 0xf: decode HTS { - 0x1: WarnUnimpl::teq(); // register - } - default: WarnUnimpl::eor(); // register - } - 0x6: WarnUnimpl::pkh(); - 0x8: decode LTRD { - 0xf: decode HTS { - 0x1: WarnUnimpl::cmn(); // register - } - default: WarnUnimpl::add(); // register - } - 0xa: WarnUnimpl::adc(); // register - 0xb: WarnUnimpl::sbc(); // register - 0xd: decode LTRD { - 0xf: decode HTS { - 0x1: WarnUnimpl::cmp(); // register - } - default: WarnUnimpl::sub(); // register - } - 0xe: WarnUnimpl::rsb(); // register - } + 0x1: Thumb32DataProcShiftReg::thumb32DataProcShiftReg(); default: decode HTOPCODE_9_8 { 0x2: decode LTOPCODE_4 { 0x0: decode LTCOPROC { @@ -280,76 +162,7 @@ } 0x2: decode LTOPCODE_15 { 0x0: decode HTOPCODE_9 { - 0x0: decode HTOPCODE_8_5 { - 0x0: decode LTRD { - 0xf: decode HTS { - 0x1: DataModImmOp::tst({{ - resTemp = Rn & rotated_imm; - }}); - } - default: DataModImmOp::and({{ - Rs = resTemp = Rn & rotated_imm; - }}); - } - 0x1: DataModImmOp::bic({{ - Rs = resTemp = Rn & ~rotated_imm; - }}); - 0x2: decode HTRN { - 0xf: DataModImmOp::mov({{ - Rs = resTemp = rotated_imm; - }}); - default: DataModImmOp::orr({{ - Rs = resTemp = Rn | rotated_imm; - }}); - } - 0x3: decode HTRN { - 0xf: DataModImmOp::mvn({{ - Rs = resTemp = ~rotated_imm; - }}); - default: DataModImmOp::orn({{ - Rs = resTemp = Rn | ~rotated_imm; - }}); - } - 0x4: decode LTRD { - 0xf: decode HTS { - 0x1: DataModImmOp::teq({{ - resTemp = Rn ^ rotated_imm; - }}); - } - default: DataModImmOp::eor({{ - Rs = resTemp = Rn ^ rotated_imm; - }}); - } - 0x8: decode LTRD { - 0xf: decode HTS { - 0x1: DataModImmOp::cmn({{ - resTemp = Rn + rotated_imm; - }}, add); - } - default: DataModImmOp::add({{ - Rs = resTemp = Rn + rotated_imm; - }}, add); - } - 0xa: DataModImmOp::adc({{ - Rs = resTemp = Rn + rotated_imm + CondCodes<29:>; - }}, add); - 0xb: DataModImmOp::sbc({{ - Rs = resTemp = Rn - rotated_imm - !CondCodes<29:>; - }}, sub); - 0xd: decode LTRD { - 0xf: decode HTS { - 0x1: DataModImmOp::cmp({{ - resTemp = Rn - rotated_imm; - }}, sub); - } - default: DataModImmOp::sub({{ - Rs = resTemp = Rn - rotated_imm; - }}, sub); - } - 0xe: DataModImmOp::rsb({{ - Rs = resTemp = rotated_imm - Rn; - }}, rsb); - } + 0x0: Thumb32DataProcModImm::thumb32DataProcModImm(); 0x1: WarnUnimpl::Data_processing_plain_binary_immediate(); } 0x1: WarnUnimpl::Branches_and_miscellaneous_control(); diff --git a/src/arch/arm/isa/formats/data.isa b/src/arch/arm/isa/formats/data.isa index 37a10f160..ee4e089f9 100644 --- a/src/arch/arm/isa/formats/data.isa +++ b/src/arch/arm/isa/formats/data.isa @@ -40,28 +40,30 @@ def format ArmDataProcReg() {{ case %(opcode)#x: if (immShift) { if (setCc) { - return new %(className)sDRegCc(machInst, - rd, rn, rm, imm5, type); + return new %(className)sDRegCc(machInst, %(dest)s, %(op1)s, + rm, imm5, type); } else { - return new %(className)sDReg(machInst, - rd, rn, rm, imm5, type); + return new %(className)sDReg(machInst, %(dest)s, %(op1)s, + rm, imm5, type); } } else { if (setCc) { - return new %(className)sDRegRegCc(machInst, - rd, rn, rm, rs, type); + return new %(className)sDRegRegCc(machInst, %(dest)s, + %(op1)s, rm, rs, type); } else { - return new %(className)sDRegReg(machInst, - rd, rn, rm, rs, type); + return new %(className)sDRegReg(machInst, %(dest)s, + %(op1)s, rm, rs, type); } } break; ''' - def instCode(opcode, mnem): + def instCode(opcode, mnem, dest="rd", op1="rn"): global instDecode return instDecode % { "className": mnem.capitalize(), - "opcode": opcode } + "opcode": opcode, + "dest": dest, + "op1": op1 } decode_block = ''' { @@ -83,14 +85,14 @@ def format ArmDataProcReg() {{ decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") - decode_block += instCode(0x8, "tst") - decode_block += instCode(0x9, "teq") - decode_block += instCode(0xa, "cmp") - decode_block += instCode(0xb, "cmn") + decode_block += instCode(0x8, "tst", dest="INTREG_ZERO") + decode_block += instCode(0x9, "teq", dest="INTREG_ZERO") + decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO") + decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO") decode_block += instCode(0xc, "orr") - decode_block += instCode(0xd, "mov") + decode_block += instCode(0xd, "mov", op1="INTREG_ZERO") decode_block += instCode(0xe, "bic") - decode_block += instCode(0xf, "mvn") + decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO") decode_block += ''' default: return new Unknown(machInst); @@ -103,17 +105,21 @@ def format ArmDataProcImm() {{ instDecode = ''' case %(opcode)#x: if (setCc) { - return new %(className)sDImmCc(machInst, rd, rn, imm, rotC); + return new %(className)sDImmCc(machInst, %(dest)s, %(op1)s, + imm, rotC); } else { - return new %(className)sDImm(machInst, rd, rn, imm, rotC); + return new %(className)sDImm(machInst, %(dest)s, %(op1)s, + imm, rotC); } break; ''' - def instCode(opcode, mnem): + def instCode(opcode, mnem, dest="rd", op1="rn"): global instDecode return instDecode % { "className": mnem.capitalize(), - "opcode": opcode } + "opcode": opcode, + "dest": dest, + "op1": op1 } decode_block = ''' { @@ -134,14 +140,14 @@ def format ArmDataProcImm() {{ decode_block += instCode(0x5, "adc") decode_block += instCode(0x6, "sbc") decode_block += instCode(0x7, "rsc") - decode_block += instCode(0x8, "tst") - decode_block += instCode(0x9, "teq") - decode_block += instCode(0xa, "cmp") - decode_block += instCode(0xb, "cmn") + decode_block += instCode(0x8, "tst", dest="INTREG_ZERO") + decode_block += instCode(0x9, "teq", dest="INTREG_ZERO") + decode_block += instCode(0xa, "cmp", dest="INTREG_ZERO") + decode_block += instCode(0xb, "cmn", dest="INTREG_ZERO") decode_block += instCode(0xc, "orr") - decode_block += instCode(0xd, "mov") + decode_block += instCode(0xd, "mov", op1="INTREG_ZERO") decode_block += instCode(0xe, "bic") - decode_block += instCode(0xf, "mvn") + decode_block += instCode(0xf, "mvn", op1="INTREG_ZERO") decode_block += ''' default: return new Unknown(machInst); @@ -149,3 +155,404 @@ def format ArmDataProcImm() {{ } ''' }}; + +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 + return new MovDReg(machInst, rd, INTREG_ZERO, rn, imm5, LSL); + case 0x1: // lsr + return new MovDReg(machInst, rd, INTREG_ZERO, rn, imm5, LSR); + case 0x2: // asr + return new MovDReg(machInst, rd, INTREG_ZERO, rn, imm5, ASR); + case 0x3: + switch (bits(machInst, 10, 9)) { + case 0x0: + return new AddDReg(machInst, rd, rn, rm, 0, LSL); + case 0x1: + return new SubDReg(machInst, rd, rn, rm, 0, LSL); + case 0x2: + return new AddDImm(machInst, rd, rn, imm3, true); + case 0x3: + return new SubDImm(machInst, rd, rn, imm3, true); + } + case 0x4: + return new MovDImm(machInst, rd8, INTREG_ZERO, imm8, true); + case 0x5: + return new CmpDImmCc(machInst, INTREG_ZERO, rd8, imm8, true); + case 0x6: + return new AddDImm(machInst, rd8, rd8, imm8, true); + case 0x7: + return new SubDImm(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: + return new AndDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x1: + return new EorDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x2: //lsl + return new MovDRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSL); + case 0x3: //lsr + return new MovDRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, LSR); + case 0x4: //asr + return new MovDRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ASR); + case 0x5: + return new AdcDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x6: + return new SbcDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x7: // ror + return new MovDRegReg(machInst, rdn, INTREG_ZERO, rdn, rm, ROR); + case 0x8: + return new TstDReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x9: + return new RsbDImm(machInst, rdn, rm, 0, true); + case 0xa: + return new CmpDReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xb: + return new CmnDReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0xc: + return new OrrDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0xd: + //XXX Implement me! + return new WarnUnimplemented("mul", machInst); + case 0xe: + return new BicDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0xf: + return new MvnDReg(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 AddDReg(machInst, rdn, rdn, rm, 0, LSL); + case 0x1: + return new CmpDReg(machInst, INTREG_ZERO, rdn, rm, 0, LSL); + case 0x2: + return new MovDReg(machInst, rdn, INTREG_ZERO, rm, 0, LSL); + case 0x3: + if (bits(machInst, 7) == 0) + return new WarnUnimplemented("bx", machInst); + else + // The register version. + return new WarnUnimplemented("blx", machInst); + } + } + ''' +}}; + +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 AddDImm(machInst, rd, INTREG_PC, imm8, true); + } + ''' +}}; + +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 AddDImm(machInst, rd, INTREG_SP, imm8, true); + } + ''' +}}; + +def format Thumb16Misc() {{ + decode_block = ''' + { + switch (bits(machInst, 11, 8)) { + case 0x0: + if (bits(machInst, 7)) { + return new SubDImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } else { + return new AddDImm(machInst, INTREG_SP, INTREG_SP, + bits(machInst, 6, 0) << 2, true); + } + case 0x1: + return new WarnUnimplemented("cbz", machInst); + case 0x2: + switch (bits(machInst, 7, 6)) { + case 0x0: + return new WarnUnimplemented("sxth", machInst); + case 0x1: + return new WarnUnimplemented("sxtb", machInst); + case 0x2: + return new WarnUnimplemented("uxth", machInst); + case 0x3: + return new WarnUnimplemented("uxtb", machInst); + } + case 0x3: + return new WarnUnimplemented("cbnz", machInst); + case 0x4: + case 0x5: + return new WarnUnimplemented("push", machInst); + case 0x6: + { + const uint32_t opBits = bits(machInst, 7, 5); + if (opBits == 2) { + return new WarnUnimplemented("setend", machInst); + } else if (opBits == 3) { + return new WarnUnimplemented("cps", machInst); + } + } + case 0x9: + return new WarnUnimplemented("cbz", machInst); + case 0xa: + switch (bits(machInst, 7, 5)) { + case 0x0: + return new WarnUnimplemented("rev", machInst); + case 0x1: + return new WarnUnimplemented("rev16", machInst); + case 0x3: + return new WarnUnimplemented("revsh", machInst); + default: + break; + } + break; + case 0xb: + return new WarnUnimplemented("cbnz", machInst); + case 0xc: + case 0xd: + return new WarnUnimplemented("pop", machInst); + case 0xe: + return new WarnUnimplemented("bkpt", machInst); + case 0xf: + if (bits(machInst, 3, 0) != 0) + return new WarnUnimplemented("it", machInst); + switch (bits(machInst, 7, 4)) { + case 0x0: + return new WarnUnimplemented("nop", machInst); + case 0x1: + return new WarnUnimplemented("yield", machInst); + case 0x2: + return new WarnUnimplemented("wfe", machInst); + case 0x3: + return new WarnUnimplemented("wfi", machInst); + case 0x4: + return new WarnUnimplemented("sev", 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)sDImmCc(machInst, %(dest)s, + %(op1)s, imm, true); + } else { + return new %(mnem)sDImm(machInst, %(dest)s, + %(op1)s, imm, true); + } + ''' % {"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 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 Thumb32DataProcShiftReg() {{ + + def decInst(mnem, dest="rd", op1="rn"): + return ''' + if (s) { + return new %(mnem)sDRegCc(machInst, %(dest)s, + %(op1)s, rm, amt, type); + } else { + return new %(mnem)sDReg(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: + return new WarnUnimplemented("pkh", machInst); + 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") + } +}}; |