summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGalen Williamson <galen@vector35.com>2025-01-21 20:06:55 -0500
committerGalen Williamson <galen@vector35.com>2025-06-09 12:40:14 -0400
commitc8de8363f3dd55ab09bfde7fcb01a11f7d0a0e94 (patch)
treee4b3fb4231163980ce972d9c5ea91b45953c7e75
parentc8f4346609f4b51474481d9e6b869076e5a96534 (diff)
[thumb2] add intrinsics for rbit and clz instructions
-rw-r--r--arch/armv7/il.h2
-rw-r--r--arch/armv7/thumb2_disasm/arch_thumb2.cpp4
-rw-r--r--arch/armv7/thumb2_disasm/il_thumb2.cpp89
3 files changed, 69 insertions, 26 deletions
diff --git a/arch/armv7/il.h b/arch/armv7/il.h
index 075c2a2e..e4a57907 100644
--- a/arch/armv7/il.h
+++ b/arch/armv7/il.h
@@ -51,6 +51,8 @@ enum Armv7Intrinsic : uint32_t
ARMV7_INTRIN_EXCLUSIVE_MONITORS_PASS,
ARMV7_INTRIN_SET_EXCLUSIVE_MONITORS,
+ ARMV7_INTRIN_RBIT,
+ ARMV7_INTRIN_CLZ,
};
enum ArmFakeRegister: uint32_t
diff --git a/arch/armv7/thumb2_disasm/arch_thumb2.cpp b/arch/armv7/thumb2_disasm/arch_thumb2.cpp
index 420dcbbb..a6b8ee0a 100644
--- a/arch/armv7/thumb2_disasm/arch_thumb2.cpp
+++ b/arch/armv7/thumb2_disasm/arch_thumb2.cpp
@@ -1403,6 +1403,10 @@ public:
return "__wfi";
case ARM_M_INTRIN_SET_BASEPRI:
return "__set_BASEPRI";
+ case ARMV7_INTRIN_RBIT:
+ return "__rbit";
+ case ARMV7_INTRIN_CLZ:
+ return "__clz";
default:
return "";
}
diff --git a/arch/armv7/thumb2_disasm/il_thumb2.cpp b/arch/armv7/thumb2_disasm/il_thumb2.cpp
index 39d9d0a0..56443ff1 100644
--- a/arch/armv7/thumb2_disasm/il_thumb2.cpp
+++ b/arch/armv7/thumb2_disasm/il_thumb2.cpp
@@ -205,6 +205,27 @@ static ExprId ReadArithOperand(LowLevelILFunction& il, decomp_result* instr, siz
return ReadShiftedOperand(il, instr, 2, size);
}
+static uint32_t GetRegisterOperand(decomp_result* instr, size_t operand)
+{
+ uint32_t reg;
+ switch (instr->format->operands[operand].type)
+ {
+ case OPERAND_FORMAT_REG:
+ reg = instr->fields[instr->format->operands[operand].field0];
+ return GetRegisterByIndex(reg);
+ case OPERAND_FORMAT_REG_FP:
+ reg = instr->fields[instr->format->operands[operand].field0];
+ return GetRegisterByIndex(reg, instr->format->operands[operand].prefix);
+ case OPERAND_FORMAT_SP:
+ return armv7::REG_SP;
+ case OPERAND_FORMAT_LR:
+ return armv7::REG_LR;
+ case OPERAND_FORMAT_PC:
+ return armv7::REG_PC;
+ default:
+ return armv7::REG_INVALID;
+ }
+}
static ExprId WriteILOperand(LowLevelILFunction& il, decomp_result* instr, size_t operand, ExprId value,
size_t size = 4, uint32_t flags = 0)
@@ -675,32 +696,41 @@ bool GetLowLevelILForThumbInstruction(Architecture* arch, LowLevelILFunction& il
(instr->pc - 4) + instr->fields[instr->format->operands[1].field0], (instr->pc - 4) + (instr->instrSize / 8));
break;
case armv7::ARMV7_CLZ:
- {
- LowLevelILLabel loopStart,
- loopBody,
- loopExit;
- //Count leading zeros
- //Based on the non-thumb CLZ lifter
- //
- // TEMP0 = 0
- // TEMP1 = op2.reg
- // while (TEMP1 != 0)
- // TEMP1 = TEMP1 >> 1
- // TEMP0 = TEMP0 + 1
- // op1.reg = 32 - TEMP0
- il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), il.Const(4, 0)));
- il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1), ReadILOperand(il, instr, 1)));
- il.AddInstruction(il.Goto(loopStart));
- il.MarkLabel(loopStart);
- il.AddInstruction(il.If(il.CompareNotEqual(4, il.Register(4, LLIL_TEMP(1)), il.Const(4, 0)), loopBody, loopExit));
- il.MarkLabel(loopBody);
- il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1), il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(4, 1))));
- il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), il.Add(4, il.Register(4, LLIL_TEMP(0)), il.Const(4, 1))));
- il.AddInstruction(il.Goto(loopStart));
- il.MarkLabel(loopExit);
- il.AddInstruction(WriteILOperand(il, instr, 0, il.Sub(4, il.Const(4, 32), il.Register(4, LLIL_TEMP(0)))));
- break;
- }
+ if (true) {
+ il.AddInstruction(
+ il.Intrinsic(
+ {RegisterOrFlag::Register(GetRegisterOperand(instr, 0))},
+ ARMV7_INTRIN_CLZ,
+ {ReadILOperand(il, instr, 1)}));
+ break;
+ }
+ else
+ {
+ LowLevelILLabel loopStart,
+ loopBody,
+ loopExit;
+ //Count leading zeros
+ //Based on the non-thumb CLZ lifter
+ //
+ // TEMP0 = 0
+ // TEMP1 = op2.reg
+ // while (TEMP1 != 0)
+ // TEMP1 = TEMP1 >> 1
+ // TEMP0 = TEMP0 + 1
+ // op1.reg = 32 - TEMP0
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), il.Const(4, 0)));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1), ReadILOperand(il, instr, 1)));
+ il.AddInstruction(il.Goto(loopStart));
+ il.MarkLabel(loopStart);
+ il.AddInstruction(il.If(il.CompareNotEqual(4, il.Register(4, LLIL_TEMP(1)), il.Const(4, 0)), loopBody, loopExit));
+ il.MarkLabel(loopBody);
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1), il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(4, 1))));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), il.Add(4, il.Register(4, LLIL_TEMP(0)), il.Const(4, 1))));
+ il.AddInstruction(il.Goto(loopStart));
+ il.MarkLabel(loopExit);
+ il.AddInstruction(WriteILOperand(il, instr, 0, il.Sub(4, il.Const(4, 32), il.Register(4, LLIL_TEMP(0)))));
+ break;
+ }
case armv7::ARMV7_CMP:
il.AddInstruction(il.Sub(4, ReadILOperand(il, instr, 0), ReadArithOperand(il, instr, 1), IL_FLAGWRITE_ALL));
break;
@@ -1160,6 +1190,13 @@ bool GetLowLevelILForThumbInstruction(Architecture* arch, LowLevelILFunction& il
case armv7::ARMV7_PUSH:
Push(il, instr->fields[FIELD_registers]);
break;
+ case armv7::ARMV7_RBIT:
+ il.AddInstruction(
+ il.Intrinsic(
+ {RegisterOrFlag::Register(GetRegisterOperand(instr, 0))},
+ ARMV7_INTRIN_RBIT,
+ {ReadILOperand(il, instr, 1)}));
+ break;
case armv7::ARMV7_REV:
il.AddInstruction(WriteILOperand(il, instr, 0,
il.Or(4, il.LogicalShiftRight(4, ReadILOperand(il, instr, 1), il.Const(4, 24)),