diff options
| author | Galen Williamson <galen@vector35.com> | 2025-01-21 20:06:55 -0500 |
|---|---|---|
| committer | Galen Williamson <galen@vector35.com> | 2025-06-09 12:40:14 -0400 |
| commit | c8de8363f3dd55ab09bfde7fcb01a11f7d0a0e94 (patch) | |
| tree | e4b3fb4231163980ce972d9c5ea91b45953c7e75 | |
| parent | c8f4346609f4b51474481d9e6b869076e5a96534 (diff) | |
[thumb2] add intrinsics for rbit and clz instructions
| -rw-r--r-- | arch/armv7/il.h | 2 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/arch_thumb2.cpp | 4 | ||||
| -rw-r--r-- | arch/armv7/thumb2_disasm/il_thumb2.cpp | 89 |
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)), |
