summaryrefslogtreecommitdiff
path: root/src/arch
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch')
-rw-r--r--src/arch/arm/isa/decoder/thumb.isa203
-rw-r--r--src/arch/arm/isa/formats/data.isa459
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")
+ }
+}};