summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjonathanzetier <207571460+jonathanzetier@users.noreply.github.com>2025-04-14 08:17:34 -0700
committerGalen Williamson <galen@vector35.com>2025-06-02 14:04:41 -0400
commit742b25d62c01f7177687a1473cd8233d371fcf36 (patch)
tree8a32d3832cafeb70856be3360a500890bf203014
parentcd2f20bc72f813684faa2b25df4f30516bcb3ba9 (diff)
Add IL for thumb2 CP instructions
-rw-r--r--arch/armv7/thumb2_disasm/arch_thumb2.cpp49
-rw-r--r--arch/armv7/thumb2_disasm/il_thumb2.cpp98
2 files changed, 146 insertions, 1 deletions
diff --git a/arch/armv7/thumb2_disasm/arch_thumb2.cpp b/arch/armv7/thumb2_disasm/arch_thumb2.cpp
index 1c38fc2c..420dcbbb 100644
--- a/arch/armv7/thumb2_disasm/arch_thumb2.cpp
+++ b/arch/armv7/thumb2_disasm/arch_thumb2.cpp
@@ -1177,7 +1177,7 @@ public:
if(reg == 15)
result.emplace_back(RegisterToken, "apsr_nzcv");
else {
- snprintf(regname, sizeof(regname), "R%d", reg);
+ get_reg_name(REG_R0 + reg, regname);
result.emplace_back(RegisterToken, regname);
}
break;
@@ -1347,6 +1347,14 @@ public:
{
switch (intrinsic)
{
+ case ARMV7_INTRIN_COPROC_GETONEWORD:
+ return "Coproc_GetOneWord";
+ case ARMV7_INTRIN_COPROC_GETTWOWORDS:
+ return "Coproc_GetTwoWords";
+ case ARMV7_INTRIN_COPROC_SENDONEWORD:
+ return "Coproc_SendOneWord";
+ case ARMV7_INTRIN_COPROC_SENDTWOWORDS:
+ return "Coproc_SendTwoWords";
case ARMV7_INTRIN_DBG:
return "__dbg";
case ARMV7_INTRIN_DMB_SY:
@@ -1403,6 +1411,10 @@ public:
virtual vector<uint32_t> GetAllIntrinsics() override
{
return vector<uint32_t> {
+ ARMV7_INTRIN_COPROC_GETONEWORD,
+ ARMV7_INTRIN_COPROC_GETTWOWORDS,
+ ARMV7_INTRIN_COPROC_SENDONEWORD,
+ ARMV7_INTRIN_COPROC_SENDTWOWORDS,
ARMV7_INTRIN_DBG,
ARMV7_INTRIN_DMB_SY,
ARMV7_INTRIN_DMB_ST,
@@ -1433,6 +1445,37 @@ public:
{
switch (intrinsic)
{
+ case ARMV7_INTRIN_COPROC_GETONEWORD:
+ return {
+ NameAndType("cp", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ NameAndType("n", Type::IntegerType(1, false)),
+ NameAndType("m", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ };
+ case ARMV7_INTRIN_COPROC_GETTWOWORDS:
+ return {
+ NameAndType("cp", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ NameAndType("m", Type::IntegerType(1, false)),
+ };
+ case ARMV7_INTRIN_COPROC_SENDONEWORD:
+ return {
+ NameAndType(Type::IntegerType(4, false)),
+ NameAndType("cp", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ NameAndType("n", Type::IntegerType(1, false)),
+ NameAndType("m", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ };
+ case ARMV7_INTRIN_COPROC_SENDTWOWORDS:
+ return {
+ NameAndType(Type::IntegerType(4, false)),
+ NameAndType(Type::IntegerType(4, false)),
+ NameAndType("cp", Type::IntegerType(1, false)),
+ NameAndType(Type::IntegerType(1, false)),
+ NameAndType("m", Type::IntegerType(1, false)),
+ };
case ARMV7_INTRIN_MRS:
return {NameAndType(Type::IntegerType(4, false))};
case ARMV7_INTRIN_MSR:
@@ -1448,6 +1491,10 @@ public:
{
switch (intrinsic)
{
+ case ARMV7_INTRIN_COPROC_GETONEWORD:
+ return { Type::IntegerType(4, false) };
+ case ARMV7_INTRIN_COPROC_GETTWOWORDS:
+ return { Type::IntegerType(4, false), Type::IntegerType(4, false) };
case ARMV7_INTRIN_MRS:
return {Type::IntegerType(4, false)};
case ARMV7_INTRIN_MSR:
diff --git a/arch/armv7/thumb2_disasm/il_thumb2.cpp b/arch/armv7/thumb2_disasm/il_thumb2.cpp
index d98b54d2..39d9d0a0 100644
--- a/arch/armv7/thumb2_disasm/il_thumb2.cpp
+++ b/arch/armv7/thumb2_disasm/il_thumb2.cpp
@@ -973,6 +973,44 @@ bool GetLowLevelILForThumbInstruction(Architecture* arch, LowLevelILFunction& il
il.AddInstruction(WriteArithOperand(il, instr, il.LogicalShiftRight(4, ReadArithOperand(il, instr, 0),
ReadArithOperand(il, instr, 1), ifThenBlock ? 0 : IL_FLAGWRITE_CNZ)));
break;
+ case armv7::ARMV7_MCR:
+ case armv7::ARMV7_MCR2:
+ {
+ int dest_reg_field = instr->fields[instr->format->operands[2].field0];
+ int dest_reg = GetRegisterByIndex(dest_reg_field, instr->format->operands[2].prefix);
+
+ il.AddInstruction(
+ il.Intrinsic({ }, ARMV7_INTRIN_COPROC_SENDONEWORD,
+ {
+ il.Register(4, dest_reg),
+ il.Const(1, instr->fields[instr->format->operands[0].field0]),
+ il.Const(1, instr->fields[instr->format->operands[1].field0]),
+ il.Const(1, instr->fields[instr->format->operands[3].field0]),
+ il.Const(1, instr->fields[instr->format->operands[4].field0]),
+ il.Const(1, instr->fields[instr->format->operands[5].field0]),
+ }
+ )
+ );
+ break;
+ }
+ case ARMV7_MCRR:
+ case ARMV7_MCRR2:
+ {
+ int rt = instr->fields[instr->format->operands[2].field0];
+ int rt2 = instr->fields[instr->format->operands[3].field0];
+ il.AddInstruction(
+ il.Intrinsic({ }, ARMV7_INTRIN_COPROC_SENDTWOWORDS,
+ {
+ il.Register(4, rt2),
+ il.Register(4, rt),
+ il.Const(1, instr->fields[instr->format->operands[0].field0]),
+ il.Const(1, instr->fields[instr->format->operands[1].field0]),
+ il.Const(1, instr->fields[instr->format->operands[4].field0]),
+ }
+ )
+ );
+ break;
+ }
case armv7::ARMV7_MLA:
il.AddInstruction(WriteILOperand(il, instr, 0, il.Add(4, ReadILOperand(il, instr, 3), il.Mult(4, ReadILOperand(il, instr, 1), ReadILOperand(il, instr, 2)))));
break;
@@ -993,6 +1031,66 @@ bool GetLowLevelILForThumbInstruction(Architecture* arch, LowLevelILFunction& il
il.ShiftLeft(4, il.Const(2, instr->fields[instr->format->operands[1].field0]), il.Const(1, 16)),
il.And(4, il.Const(4, 0x0000ffff), ReadILOperand(il, instr, 0)))));
break;
+ case armv7::ARMV7_MRC:
+ case armv7::ARMV7_MRC2:
+ {
+ auto params = {
+ il.Const(1, instr->fields[instr->format->operands[0].field0]), /* cp */
+ il.Const(1, instr->fields[instr->format->operands[1].field0]), /* opc1 */
+ il.Const(1, instr->fields[instr->format->operands[3].field0]), /* crn */
+ il.Const(1, instr->fields[instr->format->operands[4].field0]), /* crm */
+ il.Const(1, instr->fields[instr->format->operands[5].field0]), /* opc2 */
+ };
+
+ int dest_reg_field = instr->fields[instr->format->operands[2].field0];
+ if (dest_reg_field == 15)
+ {
+ il.AddInstruction(
+ il.Intrinsic(
+ { RegisterOrFlag::Register(LLIL_TEMP(0)) },
+ ARMV7_INTRIN_COPROC_GETONEWORD,
+ params
+ )
+ );
+ il.AddInstruction(il.SetFlag(IL_FLAG_N, il.TestBit(4, il.Register(4, LLIL_TEMP(0)), il.Const(1, 31))));
+ il.AddInstruction(il.SetFlag(IL_FLAG_Z, il.TestBit(4, il.Register(4, LLIL_TEMP(0)), il.Const(1, 30))));
+ il.AddInstruction(il.SetFlag(IL_FLAG_C, il.TestBit(4, il.Register(4, LLIL_TEMP(0)), il.Const(1, 29))));
+ il.AddInstruction(il.SetFlag(IL_FLAG_V, il.TestBit(4, il.Register(4, LLIL_TEMP(0)), il.Const(1, 28))));
+ break;
+ }
+
+ int dest_reg = GetRegisterByIndex(dest_reg_field, instr->format->operands[2].prefix);
+
+ il.AddInstruction(
+ il.Intrinsic(
+ {RegisterOrFlag::Register(dest_reg)}, /* outputs */
+ ARMV7_INTRIN_COPROC_GETONEWORD,
+ params /* inputs */
+ )
+ );
+ break;
+ }
+
+ case ARMV7_MRRC:
+ case ARMV7_MRRC2:
+ {
+ int rt = instr->fields[instr->format->operands[2].field0];
+ int rt2 = instr->fields[instr->format->operands[3].field0];
+
+ il.AddInstruction(
+ il.Intrinsic(
+ { RegisterOrFlag::Register(rt2), RegisterOrFlag::Register(rt) },
+ ARMV7_INTRIN_COPROC_GETTWOWORDS,
+ {
+ il.Const(1, instr->fields[instr->format->operands[0].field0]),
+ il.Const(1, instr->fields[instr->format->operands[1].field0]),
+ il.Const(1, instr->fields[instr->format->operands[4].field0]),
+ }
+ )
+ );
+ break;
+ }
+
case armv7::ARMV7_MRS:
{
int dest_reg = GetRegisterByIndex(instr->fields[instr->format->operands[0].field0], instr->format->operands[0].prefix);