ARM: Hook the external data processing instructions into the Thumb decoder.
This commit is contained in:
parent
beb759912b
commit
b66e3aec43
2 changed files with 441 additions and 221 deletions
|
@ -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();
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}};
|
||||
|
|
Loading…
Reference in a new issue