|
|
@ -38,6 +38,7 @@ static const char *opcode_names[] = {
|
|
|
|
"blx",
|
|
|
|
"blx",
|
|
|
|
"bx",
|
|
|
|
"bx",
|
|
|
|
"cdp",
|
|
|
|
"cdp",
|
|
|
|
|
|
|
|
"clrex",
|
|
|
|
"clz",
|
|
|
|
"clz",
|
|
|
|
"cmn",
|
|
|
|
"cmn",
|
|
|
|
"cmp",
|
|
|
|
"cmp",
|
|
|
@ -47,6 +48,10 @@ static const char *opcode_names[] = {
|
|
|
|
"ldr",
|
|
|
|
"ldr",
|
|
|
|
"ldrb",
|
|
|
|
"ldrb",
|
|
|
|
"ldrbt",
|
|
|
|
"ldrbt",
|
|
|
|
|
|
|
|
"ldrex",
|
|
|
|
|
|
|
|
"ldrexb",
|
|
|
|
|
|
|
|
"ldrexd",
|
|
|
|
|
|
|
|
"ldrexh",
|
|
|
|
"ldrh",
|
|
|
|
"ldrh",
|
|
|
|
"ldrsb",
|
|
|
|
"ldrsb",
|
|
|
|
"ldrsh",
|
|
|
|
"ldrsh",
|
|
|
@ -73,6 +78,10 @@ static const char *opcode_names[] = {
|
|
|
|
"str",
|
|
|
|
"str",
|
|
|
|
"strb",
|
|
|
|
"strb",
|
|
|
|
"strbt",
|
|
|
|
"strbt",
|
|
|
|
|
|
|
|
"strex",
|
|
|
|
|
|
|
|
"strexb",
|
|
|
|
|
|
|
|
"strexd",
|
|
|
|
|
|
|
|
"strexh",
|
|
|
|
"strh",
|
|
|
|
"strh",
|
|
|
|
"strt",
|
|
|
|
"strt",
|
|
|
|
"sub",
|
|
|
|
"sub",
|
|
|
@ -178,6 +187,8 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
|
|
|
|
return DisassembleBX(insn);
|
|
|
|
return DisassembleBX(insn);
|
|
|
|
case OP_CDP:
|
|
|
|
case OP_CDP:
|
|
|
|
return "cdp";
|
|
|
|
return "cdp";
|
|
|
|
|
|
|
|
case OP_CLREX:
|
|
|
|
|
|
|
|
return "clrex";
|
|
|
|
case OP_CLZ:
|
|
|
|
case OP_CLZ:
|
|
|
|
return DisassembleCLZ(insn);
|
|
|
|
return DisassembleCLZ(insn);
|
|
|
|
case OP_LDC:
|
|
|
|
case OP_LDC:
|
|
|
@ -194,6 +205,15 @@ std::string ARM_Disasm::Disassemble(uint32_t addr, uint32_t insn)
|
|
|
|
case OP_STRBT:
|
|
|
|
case OP_STRBT:
|
|
|
|
case OP_STRT:
|
|
|
|
case OP_STRT:
|
|
|
|
return DisassembleMem(insn);
|
|
|
|
return DisassembleMem(insn);
|
|
|
|
|
|
|
|
case OP_LDREX:
|
|
|
|
|
|
|
|
case OP_LDREXB:
|
|
|
|
|
|
|
|
case OP_LDREXD:
|
|
|
|
|
|
|
|
case OP_LDREXH:
|
|
|
|
|
|
|
|
case OP_STREX:
|
|
|
|
|
|
|
|
case OP_STREXB:
|
|
|
|
|
|
|
|
case OP_STREXD:
|
|
|
|
|
|
|
|
case OP_STREXH:
|
|
|
|
|
|
|
|
return DisassembleREX(opcode, insn);
|
|
|
|
case OP_LDRH:
|
|
|
|
case OP_LDRH:
|
|
|
|
case OP_LDRSB:
|
|
|
|
case OP_LDRSB:
|
|
|
|
case OP_LDRSH:
|
|
|
|
case OP_LDRSH:
|
|
|
@ -687,6 +707,36 @@ std::string ARM_Disasm::DisassemblePLD(uint32_t insn)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::string ARM_Disasm::DisassembleREX(Opcode opcode, uint32_t insn) {
|
|
|
|
|
|
|
|
uint32_t rn = BITS(insn, 16, 19);
|
|
|
|
|
|
|
|
uint32_t rd = BITS(insn, 12, 15);
|
|
|
|
|
|
|
|
uint32_t rt = BITS(insn, 0, 3);
|
|
|
|
|
|
|
|
uint32_t cond = BITS(insn, 28, 31);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (opcode) {
|
|
|
|
|
|
|
|
case OP_STREX:
|
|
|
|
|
|
|
|
case OP_STREXB:
|
|
|
|
|
|
|
|
case OP_STREXH:
|
|
|
|
|
|
|
|
return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
|
|
|
|
|
|
|
|
cond_to_str(cond), rd, rt, rn);
|
|
|
|
|
|
|
|
case OP_STREXD:
|
|
|
|
|
|
|
|
return Common::StringFromFormat("%s%s\tr%d, r%d, r%d, [r%d]", opcode_names[opcode],
|
|
|
|
|
|
|
|
cond_to_str(cond), rd, rt, rt + 1, rn);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// for LDREX instructions, rd corresponds to Rt from reference manual
|
|
|
|
|
|
|
|
case OP_LDREX:
|
|
|
|
|
|
|
|
case OP_LDREXB:
|
|
|
|
|
|
|
|
case OP_LDREXH:
|
|
|
|
|
|
|
|
return Common::StringFromFormat("%s%s\tr%d, [r%d]", opcode_names[opcode],
|
|
|
|
|
|
|
|
cond_to_str(cond), rd, rn);
|
|
|
|
|
|
|
|
case OP_LDREXD:
|
|
|
|
|
|
|
|
return Common::StringFromFormat("%s%s\tr%d, r%d, [r%d]", opcode_names[opcode],
|
|
|
|
|
|
|
|
cond_to_str(cond), rd, rd + 1, rn);
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return opcode_names[OP_UNDEFINED];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
|
|
|
|
std::string ARM_Disasm::DisassembleSWI(uint32_t insn)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
uint8_t cond = (insn >> 28) & 0xf;
|
|
|
|
uint8_t cond = (insn >> 28) & 0xf;
|
|
|
@ -739,12 +789,9 @@ Opcode ARM_Disasm::Decode00(uint32_t insn) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32_t bits7_4 = (insn >> 4) & 0xf;
|
|
|
|
uint32_t bits7_4 = (insn >> 4) & 0xf;
|
|
|
|
if (bits7_4 == 0x9) {
|
|
|
|
if (bits7_4 == 0x9) {
|
|
|
|
if ((insn & 0x0ff00ff0) == 0x01000090) {
|
|
|
|
uint32_t bit24 = BIT(insn, 24);
|
|
|
|
// Swp instruction
|
|
|
|
if (bit24) {
|
|
|
|
uint8_t bit22 = (insn >> 22) & 0x1;
|
|
|
|
return DecodeSyncPrimitive(insn);
|
|
|
|
if (bit22)
|
|
|
|
|
|
|
|
return OP_SWPB;
|
|
|
|
|
|
|
|
return OP_SWP;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// One of the multiply instructions
|
|
|
|
// One of the multiply instructions
|
|
|
|
return DecodeMUL(insn);
|
|
|
|
return DecodeMUL(insn);
|
|
|
@ -778,6 +825,10 @@ Opcode ARM_Disasm::Decode01(uint32_t insn) {
|
|
|
|
// Pre-load
|
|
|
|
// Pre-load
|
|
|
|
return OP_PLD;
|
|
|
|
return OP_PLD;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (insn == 0xf57ff01f) {
|
|
|
|
|
|
|
|
// Clear-Exclusive
|
|
|
|
|
|
|
|
return OP_CLREX;
|
|
|
|
|
|
|
|
}
|
|
|
|
if (is_load) {
|
|
|
|
if (is_load) {
|
|
|
|
if (is_byte) {
|
|
|
|
if (is_byte) {
|
|
|
|
// Load byte
|
|
|
|
// Load byte
|
|
|
@ -868,6 +919,35 @@ Opcode ARM_Disasm::Decode11(uint32_t insn) {
|
|
|
|
return OP_MCR;
|
|
|
|
return OP_MCR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Opcode ARM_Disasm::DecodeSyncPrimitive(uint32_t insn) {
|
|
|
|
|
|
|
|
uint32_t op = BITS(insn, 20, 23);
|
|
|
|
|
|
|
|
uint32_t bit22 = BIT(insn, 22);
|
|
|
|
|
|
|
|
switch (op) {
|
|
|
|
|
|
|
|
case 0x0:
|
|
|
|
|
|
|
|
if (bit22)
|
|
|
|
|
|
|
|
return OP_SWPB;
|
|
|
|
|
|
|
|
return OP_SWP;
|
|
|
|
|
|
|
|
case 0x8:
|
|
|
|
|
|
|
|
return OP_STREX;
|
|
|
|
|
|
|
|
case 0x9:
|
|
|
|
|
|
|
|
return OP_LDREX;
|
|
|
|
|
|
|
|
case 0xA:
|
|
|
|
|
|
|
|
return OP_STREXD;
|
|
|
|
|
|
|
|
case 0xB:
|
|
|
|
|
|
|
|
return OP_LDREXD;
|
|
|
|
|
|
|
|
case 0xC:
|
|
|
|
|
|
|
|
return OP_STREXB;
|
|
|
|
|
|
|
|
case 0xD:
|
|
|
|
|
|
|
|
return OP_LDREXB;
|
|
|
|
|
|
|
|
case 0xE:
|
|
|
|
|
|
|
|
return OP_STREXH;
|
|
|
|
|
|
|
|
case 0xF:
|
|
|
|
|
|
|
|
return OP_LDREXH;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
return OP_UNDEFINED;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
|
|
|
|
Opcode ARM_Disasm::DecodeMUL(uint32_t insn) {
|
|
|
|
uint8_t bit24 = (insn >> 24) & 0x1;
|
|
|
|
uint8_t bit24 = (insn >> 24) & 0x1;
|
|
|
|
if (bit24 != 0) {
|
|
|
|
if (bit24 != 0) {
|
|
|
|