summaryrefslogtreecommitdiff
path: root/arch/armv7/il.cpp
diff options
context:
space:
mode:
authorRusty Wagner <rusty.wagner@gmail.com>2024-03-05 19:50:13 -0500
committerRusty Wagner <rusty.wagner@gmail.com>2024-03-05 20:34:34 -0500
commite093c21ed880ac3eb72119be15093ee04f8ce299 (patch)
tree9f720ebdc0ae415734b1199ed341668c69710a94 /arch/armv7/il.cpp
parent0609276712622908254065546102381466033141 (diff)
Move architecture modules into the API repo
Diffstat (limited to 'arch/armv7/il.cpp')
-rw-r--r--arch/armv7/il.cpp4966
1 files changed, 4966 insertions, 0 deletions
diff --git a/arch/armv7/il.cpp b/arch/armv7/il.cpp
new file mode 100644
index 00000000..d946e77c
--- /dev/null
+++ b/arch/armv7/il.cpp
@@ -0,0 +1,4966 @@
+#include <stdarg.h>
+#include "il.h"
+#include "lowlevelilinstruction.h"
+
+using namespace BinaryNinja;
+using namespace armv7;
+
+#define ILREG(op) il.Register(get_register_size((op).reg), (op).reg)
+#define ILOFFSETREG(op) il.Register(get_register_size((op).offset), (op).offset)
+
+//Get N set bits at offset O
+#define BITMASK(N,O) (((1LL << N) - 1) << O)
+
+static inline ExprId DirectJump(Architecture* arch, LowLevelILFunction& il, uint64_t target, size_t addrSize)
+{
+ BNLowLevelILLabel* label = il.GetLabelForAddress(arch, target);
+ if (label)
+ return il.Goto(*label);
+ else
+ return il.Jump(il.ConstPointer(addrSize, target));
+
+ return 0;
+}
+
+
+static inline ExprId SetRegisterOrBranch(LowLevelILFunction& il, enum Register reg, ExprId expr, uint32_t flags=0)
+{
+ if (reg == REG_PC)
+ return il.Jump(expr);
+ else
+ return il.SetRegister(get_register_size(reg), reg, expr, flags);
+}
+
+
+static inline ExprId ReadRegisterOrPointer(LowLevelILFunction& il, const InstructionOperand& op, size_t addr)
+{
+ if (op.reg == REG_PC)
+ return il.ConstPointer(4, (addr+8));
+ return il.Register(get_register_size(op.reg), op.reg);
+}
+
+
+ExprId GetCondition(LowLevelILFunction& il, Condition cond)
+{
+ switch(cond)
+ {
+ case COND_EQ: return il.FlagCondition(LLFC_E);
+ case COND_NE: return il.FlagCondition(LLFC_NE);
+ case COND_CS: return il.FlagCondition(LLFC_UGE);
+ case COND_CC: return il.FlagCondition(LLFC_ULT);
+ case COND_MI: return il.FlagCondition(LLFC_NEG);
+ case COND_PL: return il.FlagCondition(LLFC_POS);
+ case COND_VS: return il.FlagCondition(LLFC_O);
+ case COND_VC: return il.FlagCondition(LLFC_NO);
+ case COND_HI: return il.FlagCondition(LLFC_UGT);
+ case COND_LS: return il.FlagCondition(LLFC_ULE);
+ case COND_GE: return il.FlagCondition(LLFC_SGE);
+ case COND_LT: return il.FlagCondition(LLFC_SLT);
+ case COND_GT: return il.FlagCondition(LLFC_SGT);
+ case COND_LE: return il.FlagCondition(LLFC_SLE);
+ case COND_NONE:
+ case COND_NONE2:
+ return il.Const(0, 1); //Always branch
+ default:
+ return il.Const(0, 0); //Never branch
+ }
+}
+
+static void ConditionalJump(Architecture* arch, LowLevelILFunction& il, Condition cond, size_t addrSize, uint64_t t, uint64_t f)
+{
+ BNLowLevelILLabel* trueLabel = il.GetLabelForAddress(arch, t);
+ BNLowLevelILLabel* falseLabel = il.GetLabelForAddress(arch, f);
+
+ if (UNCONDITIONAL(cond))
+ {
+ il.AddInstruction(DirectJump(arch, il, t, addrSize));
+ return;
+ }
+
+ if (trueLabel && falseLabel)
+ {
+ il.AddInstruction(il.If(GetCondition(il, cond), *trueLabel, *falseLabel));
+ return;
+ }
+
+ LowLevelILLabel trueCode, falseCode;
+
+ if (trueLabel)
+ {
+ il.AddInstruction(il.If(GetCondition(il, cond), *trueLabel, falseCode));
+ il.MarkLabel(falseCode);
+ il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f)));
+ return;
+ }
+
+ if (falseLabel)
+ {
+ il.AddInstruction(il.If(GetCondition(il, cond), trueCode, *falseLabel));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t)));
+ return;
+ }
+
+ il.AddInstruction(il.If(GetCondition(il, cond), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.Jump(il.ConstPointer(addrSize, t)));
+ il.MarkLabel(falseCode);
+ il.AddInstruction(il.Jump(il.ConstPointer(addrSize, f)));
+}
+
+
+static void ConditionExecute(LowLevelILFunction& il, Condition cond, ExprId trueCase)
+{
+ LowLevelILLabel trueCode, falseCode;
+ if (UNCONDITIONAL(cond))
+ {
+ il.AddInstruction(trueCase);
+ return;
+ }
+
+ il.AddInstruction(il.If(GetCondition(il, cond), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(trueCase);
+ il.MarkLabel(falseCode);
+}
+
+
+static ExprId GetShifted(LowLevelILFunction& il, Register reg, uint32_t ShiftAmount, Shift shift)
+{
+ if (ShiftAmount == 0)
+ return il.Register(get_register_size(reg), reg);
+
+ switch (shift)
+ {
+ case SHIFT_NONE:
+ return il.Register(get_register_size(reg), reg);
+ case SHIFT_LSR:
+ return il.LogicalShiftRight(get_register_size(reg),
+ il.Register(get_register_size(reg), reg),
+ il.Const(1, ShiftAmount));
+ case SHIFT_LSL:
+ return il.ShiftLeft(get_register_size(reg),
+ il.Register(get_register_size(reg), reg),
+ il.Const(1, ShiftAmount));
+ case SHIFT_ASR:
+ return il.ArithShiftRight(get_register_size(reg),
+ il.Register(get_register_size(reg), reg),
+ il.Const(1, ShiftAmount));
+ case SHIFT_ROR:
+ return il.RotateRight(get_register_size(reg),
+ il.Register(get_register_size(reg), reg),
+ il.Const(1, ShiftAmount));
+ case SHIFT_RRX:
+ //RRX can only shift 1 at a time
+ return il.RotateRightCarry(get_register_size(reg),
+ il.Register(get_register_size(reg), reg),
+ il.Const(1, 1), il.Flag(IL_FLAG_C));
+ default:
+ return 0;
+ }
+}
+
+
+static ExprId GetShiftedOffset(LowLevelILFunction& il, InstructionOperand& op)
+{
+ return GetShifted(il, op.offset, op.imm, op.shift);
+}
+
+
+static ExprId GetShiftedRegister(LowLevelILFunction& il, InstructionOperand& op)
+{
+ return GetShifted(il, op.reg, op.imm, op.shift);
+}
+
+
+
+static ExprId ReadAddress(LowLevelILFunction& il, InstructionOperand& op, size_t addr)
+{
+ //This should only be called by with cls or MEM_* or label
+ // <op.imm>
+ // <op.reg> +/- <op.imm>
+ // <op.reg> +/- (<op.offset> <shift> <op.imm>)
+ ExprId expr;
+ if (op.cls == LABEL)
+ return il.ConstPointer(4, op.imm);
+
+ if (op.shift == SHIFT_NONE)
+ {
+ if (op.flags.offsetRegUsed == 1)
+ {
+ expr = il.Register(get_register_size(op.offset), op.offset);
+ }
+ else
+ {
+ expr = il.Const(4, op.imm);
+ }
+ }
+ else
+ {
+ if (op.flags.offsetRegUsed == 1)
+ expr = GetShiftedOffset(il, op);
+ else
+ return GetShiftedRegister(il, op);
+ }
+
+ if (op.flags.add == 1)
+ return il.Add(4, ReadRegisterOrPointer(il, op, addr), expr);
+ else
+ return il.Sub(4, ReadRegisterOrPointer(il, op, addr), expr);
+}
+
+
+static ExprId ReadILOperand(LowLevelILFunction& il, InstructionOperand& op, size_t addr, bool isPointer=false)
+{
+ switch (op.cls)
+ {
+
+ case IMM64:
+ if (isPointer)
+ return il.ConstPointer(8, op.imm);
+ return il.Const(8, op.imm);
+ case IMM:
+ case LABEL:
+ if (isPointer)
+ return il.ConstPointer(4, op.imm);
+ return il.Const(4, op.imm);
+ case REG:
+ if (op.shift == SHIFT_NONE)
+ return ReadRegisterOrPointer(il, op, addr);
+ else if (op.flags.offsetRegUsed == 1)
+ {
+ return GetShiftedOffset(il, op);
+ }
+ else
+ {
+ return GetShiftedRegister(il, op);
+ }
+ break;
+ case MEM_IMM:
+ if (op.shift == SHIFT_NONE)
+ {
+ if (op.flags.offsetRegUsed == 1)
+ {
+ return op.flags.add?
+ il.Add(4, ReadRegisterOrPointer(il, op, addr), il.Register(get_register_size(op.reg), op.offset)):
+ il.Sub(4, ReadRegisterOrPointer(il, op, addr), il.Register(get_register_size(op.reg), op.offset));
+ }
+ else
+ {
+ if (op.imm == 0)
+ {
+ return ReadRegisterOrPointer(il, op, addr);
+ }
+ return op.flags.add?
+ il.Add(4, ReadRegisterOrPointer(il, op, addr), il.Const(4, op.imm)):
+ il.Sub(4, ReadRegisterOrPointer(il, op, addr), il.Const(4, op.imm));
+ }
+ }
+ else
+ return op.flags.add?
+ il.Add(4, ReadRegisterOrPointer(il, op, addr), GetShiftedOffset(il, op)):
+ il.Sub(4, ReadRegisterOrPointer(il, op, addr), GetShiftedOffset(il, op));
+ case MEM_PRE_IDX:
+ case MEM_POST_IDX:
+ return GetShiftedRegister(il, op);
+ case FIMM32:
+ case NONE:
+ default:
+ il.AddInstruction(il.Unimplemented());
+ break;
+ }
+ return 0;
+}
+
+
+static void Load(
+ LowLevelILFunction& il,
+ bool sx,
+ size_t size,
+ InstructionOperand& dst,
+ InstructionOperand& src,
+ size_t addr)
+{
+ ExprId value, memValue;
+ size_t dstSize = get_register_size(dst.reg);
+ value = ReadAddress(il, src, addr);
+
+ switch (src.cls)
+ {
+ case MEM_PRE_IDX:
+ memValue = il.Load(size, ILREG(src));
+
+ if (size != dstSize)
+ {
+ if (sx)
+ memValue = il.SignExtend(dstSize, memValue);
+ else
+ memValue = il.ZeroExtend(dstSize, memValue);
+ }
+
+ il.AddInstruction(SetRegisterOrBranch(il, src.reg, value));
+ il.AddInstruction(SetRegisterOrBranch(il, dst.reg, memValue));
+ break;
+ case MEM_POST_IDX:
+ memValue = il.Load(size, ILREG(src));
+
+ if (size != dstSize)
+ {
+ if (sx)
+ memValue = il.SignExtend(dstSize, memValue);
+ else
+ memValue = il.ZeroExtend(dstSize, memValue);
+ }
+
+ il.AddInstruction(SetRegisterOrBranch(il, dst.reg, memValue));
+ il.AddInstruction(SetRegisterOrBranch(il, src.reg, value));
+ break;
+ case MEM_IMM:
+ case LABEL:
+ memValue = il.Load(size, value);
+
+ if (size != dstSize)
+ {
+ if (sx)
+ memValue = il.SignExtend(dstSize, memValue);
+ else
+ memValue = il.ZeroExtend(dstSize, memValue);
+ }
+
+ il.AddInstruction(SetRegisterOrBranch(il, dst.reg, memValue));
+ break;
+ default:
+ il.AddInstruction(il.Unimplemented());
+ break;
+ }
+}
+
+
+static void LoadExclusive(
+ LowLevelILFunction& il,
+ bool sx,
+ size_t size,
+ InstructionOperand& dst,
+ InstructionOperand& src,
+ size_t addr)
+{
+ ExprId address = ReadAddress(il, src, addr);
+ size_t srcSize = get_register_size(src.reg);
+
+ il.AddInstruction(il.Intrinsic({ },
+ ARMV7_INTRIN_SET_EXCLUSIVE_MONITORS,
+ { address, il.Const(1, srcSize) }));
+ Load(il, sx, size, dst, src, addr);
+}
+
+
+static void LoadPair(
+ Architecture* arch,
+ LowLevelILFunction& il,
+ InstructionOperand& dst1,
+ InstructionOperand& dst2,
+ InstructionOperand& src,
+ size_t addr)
+{
+ ExprId address, value;
+ size_t dstSize = get_register_size(dst1.reg);
+
+ if (src.cls == MEM_PRE_IDX || src.cls == MEM_POST_IDX)
+ address = ILREG(src);
+ else
+ address = ReadAddress(il, src, addr);
+ value = il.Load(dstSize * 2, address);
+
+ if (src.cls == MEM_PRE_IDX)
+ il.AddInstruction(SetRegisterOrBranch(il, src.reg, ReadAddress(il, src, addr)));
+
+ ExprId setReg;
+ if (arch->GetEndianness() == LittleEndian)
+ setReg = il.SetRegisterSplit(dstSize, dst2.reg, dst1.reg, value);
+ else
+ setReg = il.SetRegisterSplit(dstSize, dst1.reg, dst2.reg, value);
+ il.AddInstruction(setReg);
+
+ if (src.cls == MEM_POST_IDX)
+ il.AddInstruction(SetRegisterOrBranch(il, src.reg, ReadAddress(il, src, addr)));
+}
+
+
+static void LoadPairExclusive(
+ Architecture* arch,
+ LowLevelILFunction& il,
+ InstructionOperand& dst1,
+ InstructionOperand& dst2,
+ InstructionOperand& src,
+ size_t addr)
+{
+ ExprId address = ReadAddress(il, src, addr);
+ size_t srcSize = get_register_size(src.reg);
+
+ il.AddInstruction(il.Intrinsic({ },
+ ARMV7_INTRIN_SET_EXCLUSIVE_MONITORS,
+ { address, il.Const(1, srcSize) }));
+ LoadPair(arch, il, dst1, dst2, src, addr);
+}
+
+
+static void Store(
+ LowLevelILFunction& il,
+ uint8_t size,
+ InstructionOperand& src,
+ InstructionOperand& dst,
+ size_t addr)
+{
+ ExprId address = ReadAddress(il, dst, addr);
+ size_t dstSize = get_register_size(dst.reg);
+
+ ExprId regSrc = ILREG(src);
+ size_t srcSize = get_register_size(src.reg);
+ if (size < srcSize)
+ regSrc = il.LowPart(size, regSrc);
+
+ switch (dst.cls)
+ {
+ case MEM_IMM:
+ il.AddInstruction(il.Store(size, address, regSrc));
+ break;
+ case MEM_PRE_IDX:
+ il.AddInstruction(il.SetRegister(dstSize, dst.reg, address));
+ il.AddInstruction(il.Store(size, ILREG(dst), regSrc));
+ break;
+ case MEM_POST_IDX:
+ il.AddInstruction(il.Store(size, ILREG(dst), regSrc));
+ il.AddInstruction(il.SetRegister(dstSize, dst.reg, address));
+ break;
+ default:
+ il.AddInstruction(il.Unimplemented());
+ break;
+ }
+}
+
+
+static void StoreExclusive(
+ LowLevelILFunction& il,
+ uint8_t size,
+ InstructionOperand& status,
+ InstructionOperand& src,
+ InstructionOperand& dst,
+ size_t addr)
+{
+ ExprId address = ReadAddress(il, dst, addr);
+ size_t dstSize = get_register_size(dst.reg);
+
+ LowLevelILLabel trueCode, falseCode;
+ size_t statusSize = get_register_size(status.reg);
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(status.reg) },
+ ARMV7_INTRIN_EXCLUSIVE_MONITORS_PASS,
+ { address, il.Const(1, dstSize) }));
+ il.AddInstruction(il.If(il.CompareEqual(statusSize, il.Register(statusSize, status.reg), il.Const(statusSize, 1)),
+ trueCode, falseCode));
+ il.MarkLabel(trueCode);
+
+ Store(il, size, src, dst, addr);
+
+ il.MarkLabel(falseCode);
+}
+
+
+static void StorePair(
+ Architecture* arch,
+ LowLevelILFunction& il,
+ InstructionOperand& src1,
+ InstructionOperand& src2,
+ InstructionOperand& dst,
+ size_t addr)
+{
+ ExprId address, value;
+ size_t srcSize = get_register_size(src1.reg);
+ LowLevelILLabel trueCode, falseCode;
+
+ if (dst.cls == MEM_POST_IDX)
+ address = ILREG(dst);
+ else
+ address = ReadAddress(il, dst, addr);
+
+ if (arch->GetEndianness() == LittleEndian)
+ value = il.RegisterSplit(srcSize, src2.reg, src1.reg);
+ else
+ value = il.RegisterSplit(srcSize, src1.reg, src2.reg);
+
+ il.AddInstruction(il.Store(srcSize * 2, address, value));
+
+ if (dst.cls == MEM_POST_IDX || dst.cls == MEM_PRE_IDX)
+ il.AddInstruction(SetRegisterOrBranch(il, dst.reg, ReadAddress(il, dst, addr)));
+}
+
+
+static void StorePairExclusive(
+ Architecture* arch,
+ LowLevelILFunction& il,
+ InstructionOperand& status,
+ InstructionOperand& src1,
+ InstructionOperand& src2,
+ InstructionOperand& dst,
+ size_t addr)
+{
+ ExprId address = ReadAddress(il, dst, addr);
+
+ LowLevelILLabel trueCode, falseCode;
+ size_t statusSize = get_register_size(status.reg);
+ il.AddInstruction(il.Intrinsic({ RegisterOrFlag::Register(status.reg) },
+ ARMV7_INTRIN_EXCLUSIVE_MONITORS_PASS,
+ { address, il.Const(1, 8) }));
+ il.AddInstruction(il.If(il.CompareEqual(statusSize, il.Register(statusSize, status.reg), il.Const(statusSize, 1)),
+ trueCode, falseCode));
+ il.MarkLabel(trueCode);
+
+ StorePair(arch, il, src1, src2, dst, addr);
+
+ il.MarkLabel(falseCode);
+}
+
+
+static void Saturate(LowLevelILFunction& il, uint32_t dest, ExprId to_saturate, ExprId saturate_to, bool is_signed)
+{
+
+ LowLevelILLabel trueCode, falseCode, endCode;
+ LowLevelILLabel trueCode2, falseCode2, endCode2;
+
+ if (is_signed)
+ {
+ il.AddInstruction(il.If(il.CompareSignedLessThan(4, to_saturate, il.Neg(4, saturate_to)), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.SetRegister(4, dest, il.Neg(4, saturate_to)));
+ il.AddInstruction(il.Goto(endCode));
+ il.MarkLabel(falseCode);
+ il.MarkLabel(endCode);
+
+ il.AddInstruction(il.If(il.CompareSignedGreaterThan(4, to_saturate, saturate_to), trueCode2, falseCode2));
+ il.MarkLabel(trueCode2);
+ il.AddInstruction(il.SetRegister(4, dest, saturate_to));
+ il.AddInstruction(il.Goto(endCode2));
+ il.MarkLabel(falseCode2);
+ il.AddInstruction(il.SetRegister(4, dest, to_saturate));
+ il.MarkLabel(endCode2);
+ }
+ else
+ {
+ il.AddInstruction(il.If(il.CompareSignedLessThan(4, to_saturate, il.Const(4, 0)), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ il.AddInstruction(il.SetRegister(4, dest, il.Const(4, 0)));
+ il.AddInstruction(il.Goto(endCode));
+ il.MarkLabel(falseCode);
+ il.MarkLabel(endCode);
+
+ il.AddInstruction(il.If(il.CompareSignedGreaterThan(4, to_saturate, saturate_to), trueCode2, falseCode2));
+ il.MarkLabel(trueCode2);
+ il.AddInstruction(il.SetRegister(4, dest, saturate_to));
+ il.AddInstruction(il.Goto(endCode2));
+ il.MarkLabel(falseCode2);
+ il.AddInstruction(il.SetRegister(4, dest, to_saturate));
+ il.MarkLabel(endCode2);
+ }
+}
+
+
+uint32_t GetNumberOfRegs(uint16_t regList)
+{
+ uint32_t nregs = 0;
+ for (uint32_t i = 0; i < 16; i++)
+ {
+ if (((regList >> i) & 1) == 1)
+ nregs++;
+ }
+ return nregs;
+}
+
+
+void ConditionExecute(size_t addrSize, Condition cond, Instruction& instr, LowLevelILFunction& il,
+ std::function<void (size_t addrSize, Instruction& instr, LowLevelILFunction& il)> conditionalCode)
+{
+ if (UNCONDITIONAL(cond))
+ {
+ conditionalCode(addrSize, instr, il);
+ return;
+ }
+
+ LowLevelILLabel trueLabel, falseLabel;
+ il.AddInstruction(il.If(GetCondition(il, cond), trueLabel, falseLabel));
+ il.MarkLabel(trueLabel);
+ conditionalCode(addrSize, instr, il);
+ il.AddInstruction(il.Goto(falseLabel));
+ il.MarkLabel(falseLabel);
+}
+
+void LoadOrStoreWithAdjustment(InstructionOperand& src,
+ InstructionOperand& dst,
+ LowLevelILFunction& il,
+ bool load,
+ bool increment,
+ bool before)
+{
+ if (before)
+ {
+ if (increment)
+ {
+ il.AddInstruction(il.SetRegister(get_register_size(src.reg), src.reg,
+ il.Add(get_register_size(src.reg), ILREG(src), il.Const(1, get_register_size(src.reg)))));
+ }
+ else
+ {
+ il.AddInstruction(il.SetRegister(get_register_size(src.reg), src.reg,
+ il.Sub(get_register_size(src.reg), ILREG(src), il.Const(1, get_register_size(src.reg)))));
+ }
+ }
+
+ if (load)
+ {
+ il.AddInstruction(il.SetRegister(get_register_size(dst.reg), dst.reg,
+ il.Load(get_register_size(dst.reg), ILREG(src))));
+ }
+ else
+ {
+ il.AddInstruction(il.Store(get_register_size(dst.reg), ILREG(dst), ILREG(src)));
+ }
+
+ if (!before)
+ {
+ if (increment)
+ {
+ il.AddInstruction(il.SetRegister(get_register_size(src.reg), src.reg,
+ il.Add(get_register_size(src.reg), ILREG(src), il.Const(1, get_register_size(src.reg)))));
+ }
+ else
+ {
+ il.AddInstruction(il.SetRegister(get_register_size(src.reg), src.reg,
+ il.Sub(get_register_size(src.reg), ILREG(src), il.Const(1, get_register_size(src.reg)))));
+ }
+ }
+}
+
+
+bool GetLowLevelILForArmInstruction(Architecture* arch, uint64_t addr, LowLevelILFunction& il, Instruction& instr, size_t addrSize)
+{
+ (void)arch;
+ (void)addr;
+ (void)addrSize;
+ InstructionOperand& op1 = instr.operands[0];
+ InstructionOperand& op2 = instr.operands[1];
+ InstructionOperand& op3 = instr.operands[2];
+ InstructionOperand& op4 = instr.operands[3];
+ InstructionOperand& op5 = instr.operands[4];
+ InstructionOperand& op6 = instr.operands[5];
+ LowLevelILLabel trueLabel, falseLabel, endLabel, loopBody, loopStart, loopExit;
+ uint32_t flagOperation[2] = {IL_FLAGWRITE_NONE, IL_FLAGWRITE_ALL};
+ LowLevelILLabel trueCode, falseCode, endCode;
+ switch (instr.operation)
+ {
+ case ARMV7_ADD:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_ADDW:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), IL_FLAGWRITE_NONE)));
+ break;
+ case ARMV7_ADC:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.AddCarry(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), il.Flag(IL_FLAG_C), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_ADR:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.ConstPointer(get_register_size(op1.reg), op2.imm)));
+ break;
+ case ARMV7_AND:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_ASR:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.ArithShiftRight(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_B:
+ ConditionalJump(arch, il, instr.cond, addrSize, op1.imm, addr + 4);
+ return false;
+ case ARMV7_BFC:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op1.reg), ReadRegisterOrPointer(il, op1, addr),
+ il.Const(get_register_size(op1.reg), ~(((1<<op3.imm) - 1) << op2.imm)))));
+ break;
+ case ARMV7_BFI:
+ {
+ uint32_t lsb = op3.imm;
+ uint32_t width_mask = (1<<op4.imm) - 1;
+ uint32_t mask = width_mask << lsb;
+
+ //bit field insert: op1 = (op1 & (~(<width_mask> << lsb))) | ((op2 & <width_mask>) << lsb)
+ //width_mask = (1<<width)-1
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Or(get_register_size(op1.reg),
+ il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, ~mask)
+ ),
+ il.ShiftLeft(4,
+ il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(get_register_size(op1.reg), width_mask)
+ ),
+ il.Const(4, lsb)))));
+ break;
+ }
+ case ARMV7_BKPT:
+ il.AddInstruction(il.Breakpoint());
+ break;
+ case ARMV7_BL:
+ ConditionExecute(il, instr.cond, il.Call(il.ConstPointer(4, op1.imm)));
+ break;
+ case ARMV7_BXJ:
+ case ARMV7_BX:
+ ConditionExecute(il, instr.cond, il.Jump(ReadILOperand(il, op1, addr, true)));
+ break;
+ case ARMV7_BLX:
+ ConditionExecute(il, instr.cond, il.Call(ReadILOperand(il, op1, addr, true)));
+ break;
+ case ARMV7_BIC:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Not(get_register_size(op2.reg),
+ ReadILOperand(il, op3, addr)), flagOperation[instr.setsFlags]
+ )));
+ break;
+ case ARMV7_CLZ:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ //Count leading zeros
+ //
+ // 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), ReadRegisterOrPointer(il, op2, addr)));
+ 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(SetRegisterOrBranch(il, op1.reg, il.Sub(4, il.Const(4, 32), il.Register(4, LLIL_TEMP(0)))));
+ });
+ break;
+ case ARMV7_CMN:
+ ConditionExecute(il, instr.cond, il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadILOperand(il, op2, addr), IL_FLAGWRITE_ALL));
+ break;
+ case ARMV7_CMP:
+ ConditionExecute(il, instr.cond, il.Sub(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadILOperand(il, op2, addr), IL_FLAGWRITE_ALL));
+ break;
+ case ARMV7_EOR:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Xor(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_LDM:
+ case ARMV7_LDMIA:
+ case ARMV7_LDMIB:
+ case ARMV7_LDMDA:
+ case ARMV7_LDMDB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ //Cache src address register in case it's mutated by loads
+ ExprId base = 0;
+ switch (instr.operation)
+ {
+ case ARMV7_LDM:
+ case ARMV7_LDMIA:
+ base = ILREG(op1);
+ break;
+ case ARMV7_LDMIB:
+ base = il.Add(4, ILREG(op1), il.Const(1, 4));
+ break;
+ case ARMV7_LDMDB:
+ base = il.Sub(4, ILREG(op1), il.Const(1, 4 * GetNumberOfRegs(op2.reg)));
+ break;
+ case ARMV7_LDMDA:
+ base = il.Sub(4, ILREG(op1), il.Const(1, 4 * GetNumberOfRegs(op2.reg) - 4));
+ break;
+ default:
+ break;
+ }
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), base));
+
+ for (int reg = 0, slot = 0; reg < 16; reg++)
+ {
+ if (op2.reg & 1 << reg)
+ {
+ il.AddInstruction(
+ il.SetRegister(4,
+ // writes to PC are deferred to a final Jump
+ (reg != REG_PC) ? reg : LLIL_TEMP(1),
+ il.Load(4,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 4 * slot++)
+ )
+ )
+ )
+ );
+ }
+ }
+ if (op1.flags.wb)
+ {
+ ExprId wb;
+ switch (instr.operation)
+ {
+ case ARMV7_LDM:
+ case ARMV7_LDMIA:
+ wb = il.Const(1, 4 * GetNumberOfRegs(op2.reg));
+ wb = il.Add(4, il.Register(4, LLIL_TEMP(0)), wb);
+ break;
+ case ARMV7_LDMIB:
+ wb = il.Const(1, 4 * GetNumberOfRegs(op2.reg) - 4);
+ wb = il.Add(4, il.Register(4, LLIL_TEMP(0)), wb);
+ break;
+ case ARMV7_LDMDB:
+ wb = il.Register(4, LLIL_TEMP(0));
+ break;
+ case ARMV7_LDMDA:
+ wb = il.Const(1, 4);
+ wb = il.Sub(4, il.Register(4, LLIL_TEMP(0)), wb);
+ break;
+ default:
+ break;
+ }
+ //if (1 << op1.reg & op2.reg) [[unlikely]] {
+ if (1 << op1.reg & op2.reg) {
+ wb = il.Undefined();
+ }
+ il.AddInstruction(il.SetRegister(4, op1.reg, wb));
+ }
+ if (op2.reg & REG_LIST_PC)
+ {
+ il.AddInstruction(il.Jump(il.Register(4, LLIL_TEMP(1))));
+ }
+ });
+ break;
+ case ARMV7_LDREX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ LoadExclusive(il, false, 4, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDR:
+ case ARMV7_LDRT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, false, 4, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDREXH:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ LoadExclusive(il, false, 2, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDRH:
+ case ARMV7_LDRHT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, false, 2, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDREXB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ LoadExclusive(il, false, 1, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDRB:
+ case ARMV7_LDRBT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, false, 1, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDRSH:
+ case ARMV7_LDRSHT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, true, 2, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDRSB:
+ case ARMV7_LDRSBT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, true, 1, op1, op2, addr);
+ });
+ break;
+ case ARMV7_LDREXD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ LoadPairExclusive(arch, il, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_LDRD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ LoadPair(arch, il, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_LSL:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.ShiftLeft(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_LSR:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.LogicalShiftRight(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_MCR:
+ case ARMV7_MCR2:
+ ConditionExecute(il, instr.cond,
+ il.Intrinsic({ }, ARMV7_INTRIN_COPROC_SENDONEWORD,
+ {
+ il.Register(4, op3.reg),
+ il.Const(1, op1.reg),
+ il.Const(1, op2.imm),
+ il.Const(1, op4.reg),
+ il.Const(1, op5.reg),
+ il.Const(1, op6.imm),
+ }
+ )
+ );
+ break;
+ case ARMV7_MCRR:
+ case ARMV7_MCRR2:
+ ConditionExecute(il, instr.cond,
+ il.Intrinsic({ }, ARMV7_INTRIN_COPROC_SENDTWOWORDS,
+ {
+ il.Register(4, op4.reg),
+ il.Register(4, op3.reg),
+ il.Const(1, op1.reg),
+ il.Const(1, op2.imm),
+ il.Const(1, op5.reg),
+ }
+ )
+ );
+ break;
+ case ARMV7_MLA:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op4, addr),
+ il.Mult(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ (op3.cls == NONE) ? ReadRegisterOrPointer(il, op1, addr) : ReadRegisterOrPointer(il, op3, addr)),
+ instr.setsFlags ? IL_FLAGWRITE_NZ : IL_FLAGWRITE_NONE)));
+ break;
+ case ARMV7_MLS:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Sub(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op4, addr),
+ il.Mult(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ (op3.cls == NONE) ? ReadRegisterOrPointer(il, op1, addr) : ReadRegisterOrPointer(il, op3, addr)),
+ flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_MOV:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ ReadILOperand(il, op2, addr),
+ instr.setsFlags ? IL_FLAGWRITE_NZ : IL_FLAGWRITE_NONE));
+ break;
+ case ARMV7_MOVT:
+ // op1.reg = (op2.imm << 16) | (op1 & 0x0000ffff)
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Const(2, op2.imm), il.Const(1,16)),
+ il.And(4, il.Const(4, 0x0000ffff), ReadRegisterOrPointer(il, op1, addr)))));
+ break;
+ case ARMV7_MOVW:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg, il.Const(4, op2.imm)));
+ break;
+ case ARMV7_MRC:
+ case ARMV7_MRC2:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void)addrSize;
+ (void)instr;
+ auto params = {
+ il.Const(1, op1.reg),
+ il.Const(1, op2.imm),
+ il.Const(1, op4.reg),
+ il.Const(1, op5.reg),
+ il.Const(1, op6.imm),
+ };
+ switch (op3.cls) {
+ case REG:
+ il.AddInstruction(
+ il.Intrinsic(
+ { RegisterOrFlag::Register(op3.reg) },
+ ARMV7_INTRIN_COPROC_GETONEWORD,
+ params
+ )
+ );
+ break;
+ case REG_SPEC:
+ 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;
+ default:
+ break;
+ }
+ });
+ break;
+ case ARMV7_MRRC:
+ case ARMV7_MRRC2:
+ ConditionExecute(il, instr.cond,
+ il.Intrinsic(
+ { RegisterOrFlag::Register(op4.reg), RegisterOrFlag::Register(op3.reg) },
+ ARMV7_INTRIN_COPROC_GETTWOWORDS,
+ {
+ il.Const(1, op1.reg),
+ il.Const(1, op2.imm),
+ il.Const(1, op5.reg),
+ }
+ )
+ );
+ break;
+ case ARMV7_MUL:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Mult(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ (op3.cls == NONE) ? ReadRegisterOrPointer(il, op1, addr) : ReadRegisterOrPointer(il, op3, addr),
+ instr.setsFlags ? IL_FLAGWRITE_NZ : IL_FLAGWRITE_NONE)));
+ break;
+ case ARMV7_MVN:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Not(get_register_size(op2.reg),
+ ReadILOperand(il, op2, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_NOP:
+ case ARMV7_DSB:
+ case ARMV7_DMB:
+ case ARMV7_ISB:
+ ConditionExecute(il, instr.cond, il.Nop());
+ break;
+ case ARMV7_ORR:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Or(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_PKHBT:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Or(4,
+ il.And(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(4, 0xffff0000)),
+ il.And(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(2, 0xffff))
+ )
+ ));
+ break;
+ case ARMV7_PKHTB:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Or(4,
+ il.And(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(4, 0xffff0000)),
+ il.And(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(2, 0xffff))
+ )
+ ));
+ break;
+ case ARMV7_POP:
+ if (CONDITIONAL(instr.cond))
+ {
+ il.AddInstruction(il.If(GetCondition(il, instr.cond), trueCode, falseCode));
+ il.MarkLabel(trueCode);
+ }
+ for (int32_t j = 0; j <= 15; j++)
+ {
+ if (((op1.reg >> j) & 1) == 1)
+ {
+ if (1 << j == REG_LIST_PC)
+ {
+ il.AddInstruction(
+ il.SetRegister(4, LLIL_TEMP(0),
+ il.Pop(get_register_size((enum Register)j))));
+ }
+ else
+ {
+ il.AddInstruction(SetRegisterOrBranch(il, (Register)j,
+ il.Pop(get_register_size((enum Register)j))));
+ }
+
+ }
+ }
+ if ((op1.reg & REG_LIST_PC) == REG_LIST_PC)
+ il.AddInstruction(il.Jump(il.Register(4, LLIL_TEMP(0))));
+
+ if (CONDITIONAL(instr.cond))
+ il.MarkLabel(falseCode);
+ break;
+ case ARMV7_PUSH:
+
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ for (int32_t j = 15; j >= 0; j--)
+ {
+ if (((op1.reg >> j) & 1) == 1)
+ {
+ il.AddInstruction(il.Push(get_register_size((enum Register)j),
+ il.Register(get_register_size((enum Register)j), j)));
+ }
+ }
+ });
+ break;
+ case ARMV7_QADD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadRegisterOrPointer(il, op3, addr)
+ )));
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Or(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Neg(get_register_size(op1.reg),
+ il.CompareSignedLessThan(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ )))));
+ });
+ break;
+ case ARMV7_QADD16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Add(2,
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op2, addr)),
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op3, addr))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Or(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareSignedLessThan(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2, ReadRegisterOrPointer(il, op2, addr))))))
+ ));
+
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Add(2,
+ il.LowPart(2, il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16))),
+ il.LowPart(2, il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 16)))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Or(2,
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareSignedLessThan(get_register_size(op2.reg),
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16)))))
+ ))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 0x10)),
+ il.Register(2, LLIL_TEMP(0))
+ )));
+ });
+ break;
+ case ARMV7_UQADD16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Add(2,
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op2, addr)),
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op3, addr))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Or(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareUnsignedLessThan(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2, ReadRegisterOrPointer(il, op2, addr))))))
+ ));
+
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Add(2,
+ il.LowPart(2, il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16))),
+ il.LowPart(2, il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 16)))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Or(2,
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareUnsignedLessThan(get_register_size(op2.reg),
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16)))))
+ ))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 0x10)),
+ il.Register(2, LLIL_TEMP(0))
+ )));
+ });
+ break;
+ case ARMV7_QADD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Add(1,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 8*i))))));
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Or(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.Neg(1,
+ il.CompareSignedLessThan(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))))))));
+ }
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1,24)),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1,16))),
+ il.Or(2,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1,8)),
+ il.Register(1, LLIL_TEMP(0))))));
+ });
+ break;
+ case ARMV7_UQADD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Add(1,
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))),
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 8*i))))));
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Or(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.Neg(1,
+ il.CompareUnsignedLessThan(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))))))));
+ }
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1,24)),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1,16))),
+ il.Or(2,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1,8)),
+ il.Register(1, LLIL_TEMP(0))))));
+ });
+ break;
+ case ARMV7_QDADD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Add(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Mult(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 2))
+ )));
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Or(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Neg(get_register_size(op1.reg),
+ il.CompareSignedLessThan(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ )))));
+ });
+ break;
+ case ARMV7_QASX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+
+ Saturate(il, LLIL_TEMP(2), il.Register(4, LLIL_TEMP(0)), il.Const(2, 0x7fff), true);
+ Saturate(il, LLIL_TEMP(3), il.Register(4, LLIL_TEMP(1)), il.Const(2, 0x7fff), true);
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(3)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(2))
+ )
+ ));
+ });
+ break;
+ case ARMV7_QSAX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+
+ Saturate(il, LLIL_TEMP(2), il.Register(4, LLIL_TEMP(0)), il.Const(2, 0x7fff), true);
+ Saturate(il, LLIL_TEMP(3), il.Register(4, LLIL_TEMP(1)), il.Const(2, 0x7fff), true);
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(3)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(2))
+ )
+ ));
+ });
+ break;
+ case ARMV7_QDSUB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Sub(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Mult(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 2))
+ )));
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Neg(get_register_size(op1.reg),
+ il.CompareSignedLessEqual(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ )))));
+ });
+ break;
+ case ARMV7_QSUB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.Sub(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadRegisterOrPointer(il, op3, addr)
+ )));
+ il.AddInstruction(il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Neg(get_register_size(op1.reg),
+ il.CompareSignedLessEqual(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ )))));
+ });
+ break;
+ case ARMV7_QSUB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Sub(2,
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op2, addr)),
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op3, addr))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.And(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareSignedLessEqual(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2, ReadRegisterOrPointer(il, op2, addr))))))
+ ));
+
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Sub(2,
+ il.LowPart(2, il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16))),
+ il.LowPart(2, il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 16)))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.And(2,
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareSignedLessEqual(get_register_size(op2.reg),
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16)))))
+ ))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 0x10)),
+ il.Register(2, LLIL_TEMP(0))
+ )));
+ });
+ break;
+ case ARMV7_UQSUB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Sub(2,
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op2, addr)),
+ il.LowPart(2,
+ ReadRegisterOrPointer(il, op3, addr))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.And(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareUnsignedLessEqual(2,
+ il.Register(2, LLIL_TEMP(0)),
+ il.LowPart(2, ReadRegisterOrPointer(il, op2, addr))))))
+ ));
+
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.Sub(2,
+ il.LowPart(2, il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16))),
+ il.LowPart(2, il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 16)))
+ )));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1),
+ il.And(2,
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.Neg(2,
+ il.CompareUnsignedLessEqual(get_register_size(op2.reg),
+ il.Register(2, LLIL_TEMP(1)),
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 16)))))
+ ))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 0x10)),
+ il.Register(2, LLIL_TEMP(0))
+ )));
+ });
+ break;
+ case ARMV7_QSUB8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Sub(1,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 8*i))))));
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.And(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.Neg(1,
+ il.CompareSignedLessEqual(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))))))));
+ }
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1,24)),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1,16))),
+ il.Or(2,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1,8)),
+ il.Register(1, LLIL_TEMP(0))))));
+ });
+ break;
+ case ARMV7_UQSUB8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.Sub(1,
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))),
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Const(1, 8*i))))));
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(i),
+ il.And(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.Neg(1,
+ il.CompareSignedLessEqual(1,
+ il.Register(1, LLIL_TEMP(i)),
+ il.LowPart(1,
+ il.LogicalShiftRight(4,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 8*i))))))));
+ }
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1,24)),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1,16))),
+ il.Or(2,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1,8)),
+ il.Register(1, LLIL_TEMP(0))))));
+ });
+ break;
+ case ARMV7_RBIT:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ //Reverse bits
+ //
+ // TEMP0 = 0
+ // TEMP1 = op2.reg
+ // TEMP2 = 0
+ // while (TEMP0 != 31)
+ // TEMP2 = TEMP2 | (TEMP1 & 1)
+ // TEMP2 = TEMP2 << 1
+ // 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), ReadRegisterOrPointer(il, op2, addr)));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2), il.Const(4, 0)));
+ il.AddInstruction(il.Goto(loopStart));
+ il.MarkLabel(loopStart);
+ il.AddInstruction(il.If(il.CompareNotEqual(4, il.Register(4, LLIL_TEMP(0)), il.Const(4, 31)), loopBody, loopExit));
+ il.MarkLabel(loopBody);
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2), il.Or(4, il.Register(4, LLIL_TEMP(2)), il.And(4, il.Register(4, LLIL_TEMP(1)), il.Const(4,1)))));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2), il.ShiftLeft(4, il.Register(4, LLIL_TEMP(2)), il.Const(4,1))));
+ 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(SetRegisterOrBranch(il, op1.reg, il.Register(4, LLIL_TEMP(2))));
+ });
+ break;
+ case ARMV7_REV:
+ ConditionExecute(il, instr.cond, il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.LogicalShiftRight(4, il.Register(4, op2.reg), il.Const(1, 24)),
+ il.Or(4,
+ il.ShiftLeft(4, il.And(4, il.LogicalShiftRight(4, il.Register(4, op2.reg), il.Const(1, 16)), il.Const(4, 0xff)), il.Const(1, 8)),
+ il.Or(4,
+ il.ShiftLeft(4, il.And(4, il.LogicalShiftRight(4, il.Register(4, op2.reg), il.Const(1, 8)), il.Const(4, 0xff)), il.Const(1, 16)),
+ il.ShiftLeft(4, il.And(4, il.Register(4, op2.reg), il.Const(4, 0xff)), il.Const(1, 24))
+ )
+ )
+ ),
+ flagOperation[instr.setsFlags]));
+ break;
+ case ARMV7_REV16:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0), il.RotateRight(2, il.LowPart(2, ReadILOperand(il, op2, addr)), il.Const(1, 16))));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1), il.RotateRight(2, il.LogicalShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1, 16)), il.Const(1, 16))));
+ il.AddInstruction(il.SetRegister(4, op1.reg, il.Or(4, il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 16)), il.Register(2, LLIL_TEMP(0)))));
+ });
+ break;
+ case ARMV7_REVSH:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0), il.RotateRight(2, il.LowPart(2, ReadILOperand(il, op2, addr)), il.Const(1, 16))));
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(1), il.RotateRight(2, il.LogicalShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1, 16)), il.Const(1, 16))));
+ il.AddInstruction(il.SetRegister(4, op1.reg, il.SignExtend(4, il.Or(4, il.ShiftLeft(4, il.Register(2, LLIL_TEMP(1)), il.Const(1, 16)), il.Register(2, LLIL_TEMP(0))))));
+ });
+ break;
+
+ case ARMV7_RSB:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.Sub(get_register_size(op2.reg),
+ ReadILOperand(il, op3, addr),
+ ReadRegisterOrPointer(il, op2, addr),
+ flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_RSC:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.SubBorrow(get_register_size(op2.reg),
+ ReadILOperand(il, op3, addr),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Not(1,il.Flag(IL_FLAG_C))),
+ flagOperation[instr.setsFlags]));
+ break;
+ case ARMV7_ROR:
+ case ARMV7_RORS:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.RotateRight(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ il.And(1,
+ ReadILOperand(il, op3, addr),
+ il.Const(1, 0xff)
+ ),
+ flagOperation[instr.setsFlags]
+ )
+ )
+ );
+ break;
+ case ARMV7_RRX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.Flag(IL_FLAG_C), il.Const(1,31)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1,1))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SADD16: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(2,
+ il.Add(2,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, LLIL_TEMP(1),
+ il.And(2,
+ il.Add(2,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.And(2,
+ il.Register(4, LLIL_TEMP(1)), il.Const(2, 0xffff)
+ ),
+ il.Const(1, 16)
+ ),
+ il.And(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(2, 0xffff)
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UADD16: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(2,
+ il.Add(2,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, LLIL_TEMP(1),
+ il.And(2,
+ il.Add(2,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.And(2,
+ il.Register(4, LLIL_TEMP(1)), il.Const(2, 0xffff)
+ ),
+ il.Const(1, 16)
+ ),
+ il.And(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(2, 0xffff)
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SADD8: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(1,
+ il.Add(1,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(1),
+ il.And(1,
+ il.Add(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(2),
+ il.And(1,
+ il.Add(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(3),
+ il.And(1,
+ il.Add(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1, 24)
+ ),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.Or(4,
+ il.ShiftLeft(2,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1, 8)
+ ),
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UADD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(1,
+ il.Add(1,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(1),
+ il.And(1,
+ il.Add(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(2),
+ il.And(1,
+ il.Add(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(3),
+ il.And(1,
+ il.Add(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1, 24)
+ ),
+ il.ShiftLeft(3,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.Or(4,
+ il.ShiftLeft(2,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1, 8)
+ ),
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SASX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(1)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UASX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(1)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SHASX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Const(1,1)
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 1)
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHASX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Const(1,1)
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 1)
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SHSAX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Const(1,1)
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.LowPart(2,
+ il.ArithShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 1)
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHSAX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Const(1,1)
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.LowPart(2,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 1)
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SSAX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.ArithShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(1)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UMAAL:
+ /* op2:op1 = op4 * op3 + op2 + op1 */
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(
+ il.SetRegisterSplit(4,
+ op2.reg, /* hi result */
+ op1.reg, /* lo result */
+ il.Add(8,
+ il.MultDoublePrecUnsigned(4,
+ il.Register(4, op4.reg),
+ il.Register(4, op3.reg)
+ ),
+ il.Add(8,
+ il.Register(4, op2.reg),
+ il.Register(4, op1.reg)
+ )
+ )
+ )
+ );
+ });
+ break;
+ case ARMV7_UMLAL:
+ /* op2:op1 = op4 * op3 + op2:op1 */
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(
+ il.SetRegisterSplit(4,
+ op2.reg, /* hi result */
+ op1.reg, /* lo result */
+ il.Add(8,
+ il.MultDoublePrecUnsigned(4,
+ il.Register(4, op4.reg),
+ il.Register(4, op3.reg)
+ ),
+ il.RegisterSplit(
+ 4,
+ op2.reg,
+ op1.reg
+ )
+ ),
+ instr.setsFlags ? IL_FLAGWRITE_NZ : IL_FLAGWRITE_NONE
+ )
+ );
+ });
+ break;
+ case ARMV7_SSUB16: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(2,
+ il.Sub(2,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, LLIL_TEMP(1),
+ il.And(2,
+ il.Sub(2,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.And(2,
+ il.Register(4, LLIL_TEMP(1)), il.Const(2, 0xffff)
+ ),
+ il.Const(1, 16)
+ ),
+ il.And(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(2, 0xffff)
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_USUB16: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(2,
+ il.Sub(2,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, LLIL_TEMP(1),
+ il.And(2,
+ il.Sub(2,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(2, 0xffff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.And(2,
+ il.Register(4, LLIL_TEMP(1)), il.Const(2, 0xffff)
+ ),
+ il.Const(1, 16)
+ ),
+ il.And(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(2, 0xffff)
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SSUB8: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(1,
+ il.Sub(1,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(1),
+ il.And(1,
+ il.Sub(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(2),
+ il.And(1,
+ il.Sub(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(3),
+ il.And(1,
+ il.Sub(1,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1, 24)
+ ),
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1, 8)
+ ),
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_USUB8: //TODO: APSR
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.And(1,
+ il.Sub(1,
+ ReadILOperand(il, op2, addr),
+ ReadILOperand(il, op3, addr)
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(1),
+ il.And(1,
+ il.Sub(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(2),
+ il.And(1,
+ il.Sub(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(1, LLIL_TEMP(3),
+ il.And(1,
+ il.Sub(1,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ ),
+ il.Const(1, 0xff)
+ )));
+ il.AddInstruction(
+ il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(3)),
+ il.Const(1, 24)
+ ),
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(1, LLIL_TEMP(1)),
+ il.Const(1, 8)
+ ),
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SBC:
+ case ARMV7_SBCS:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.SubBorrow(get_register_size(op2.reg),
+ ReadILOperand(il, op2, addr),
+ ReadRegisterOrPointer(il, op3, addr),
+ il.Not(1,il.Flag(IL_FLAG_C))),
+ flagOperation[instr.setsFlags]));
+ break;
+ case ARMV7_SBFX:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.ArithShiftRight(get_register_size(op1.reg),
+ il.ShiftLeft(get_register_size(op2.reg),
+ ReadILOperand(il, op2, addr),
+ il.Const(1, (get_register_size(op2.reg) * 8) - op3.imm - op4.imm)),
+ il.Const(1, (get_register_size(op2.reg) * 8) - op4.imm))));
+ break;
+ case ARMV7_SDIV:
+ if (op3.cls == NONE)
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.DivSigned(get_register_size(op1.reg), ReadRegisterOrPointer(il, op1, addr), ReadRegisterOrPointer(il, op2, addr))));
+ else
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.DivSigned(get_register_size(op2.reg), ReadRegisterOrPointer(il, op2, addr), ReadRegisterOrPointer(il, op3, addr))));
+ break;
+ case ARMV7_SHADD16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,16)),
+ il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHADD16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,16)),
+ il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SHADD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2),
+ il.Add(4,
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8))),
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(3),
+ il.Add(4,
+ il.LowPart(1, ReadILOperand(il, op2, addr)),
+ il.LowPart(1, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,24)),
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1)), il.Const(1,16))
+ ),
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(2)), il.Const(1,1)), il.Const(1,8)),
+ il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(3)), il.Const(1,1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHADD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Add(4,
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2),
+ il.Add(4,
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8))),
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(3),
+ il.Add(4,
+ il.LowPart(1, ReadILOperand(il, op2, addr)),
+ il.LowPart(1, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,24)),
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1)), il.Const(1,16))
+ ),
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(2)), il.Const(1,1)), il.Const(1,8)),
+ il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(3)), il.Const(1,1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SHSUB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,16)),
+ il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHSUB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,16)),
+ il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SHSUB8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2),
+ il.Sub(4,
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8))),
+ il.LowPart(1, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(3),
+ il.Sub(4,
+ il.LowPart(1, ReadILOperand(il, op2, addr)),
+ il.LowPart(1, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,24)),
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1)), il.Const(1,16))
+ ),
+ il.Or(4,
+ il.ShiftLeft(4, il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(2)), il.Const(1,1)), il.Const(1,8)),
+ il.ArithShiftRight(4, il.Register(4, LLIL_TEMP(3)), il.Const(1,1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UHSUB8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 24)),
+ il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 24))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(2),
+ il.Sub(4,
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 8))),
+ il.LowPart(1, il.LogicalShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 8)))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(3),
+ il.Sub(4,
+ il.LowPart(1, ReadILOperand(il, op2, addr)),
+ il.LowPart(1, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(0)), il.Const(1,1)), il.Const(1,24)),
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(1)), il.Const(1,1)), il.Const(1,16))
+ ),
+ il.Or(4,
+ il.ShiftLeft(4, il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(2)), il.Const(1,1)), il.Const(1,8)),
+ il.LogicalShiftRight(4, il.Register(4, LLIL_TEMP(3)), il.Const(1,1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLABB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLABT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLATB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Mult(4,
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLATT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Mult(4,
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLAD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1,16)),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadILOperand(il, op4, addr),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLADX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1,16)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadILOperand(il, op4, addr),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLAL:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Mult(8, ReadILOperand(il, op3, addr), ReadILOperand(il, op4, addr))));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(1),
+ il.Add(8,
+ il.Or(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op1, addr)
+ ),
+ il.Register(8, LLIL_TEMP(0))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op2.reg,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(1)),
+ il.Const(1, 32)
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Register(8, LLIL_TEMP(1))
+ ),
+ flagOperation[instr.setsFlags])
+ );
+ });
+ break;
+ case ARMV7_SMLALBB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.SignExtend(8,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLALBT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.SignExtend(8,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLALTB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.SignExtend(8,
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLALTT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.SignExtend(8,
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLALD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op3, addr)),
+ il.LowPart(2, ReadILOperand(il, op4, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16)),
+ il.ArithShiftRight(2, ReadILOperand(il, op4, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(2),
+ il.Add(8,
+ il.Or(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op1, addr)
+ ),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Register(8, LLIL_TEMP(2))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op2.reg,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(2)),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLALDX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op3, addr)),
+ il.ArithShiftRight(2, ReadILOperand(il, op4, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16)),
+ il.LowPart(2, ReadILOperand(il, op4, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(2),
+ il.Add(8,
+ il.Or(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op1, addr)
+ ),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Register(8, LLIL_TEMP(2))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op2.reg,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(2)),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLAWB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.Mult(8,
+ ReadILOperand(il, op2, addr),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ ),
+ il.ShiftLeft(8,
+ ReadILOperand(il, op4, addr),
+ il.Const(1, 16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.And(4,
+ il.ArithShiftRight(8,
+ il.Register(8, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ ),
+ il.Const(4, 0xffffffff)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLAWT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0),
+ il.Add(8,
+ il.Mult(8,
+ ReadILOperand(il, op2, addr),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ ),
+ il.ShiftLeft(8,
+ ReadILOperand(il, op4, addr),
+ il.Const(1, 16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.And(4,
+ il.ArithShiftRight(8,
+ il.Register(8, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ ),
+ il.Const(4, 0xffffffff)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLSD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLSDX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLSLD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op3, addr)),
+ il.LowPart(2, ReadILOperand(il, op4, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16)),
+ il.ArithShiftRight(2, ReadILOperand(il, op4, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(2),
+ il.Add(8,
+ il.Or(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op1, addr)
+ ),
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Register(8, LLIL_TEMP(2))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op2.reg,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(2)),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMLSLDX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op3, addr)),
+ il.ArithShiftRight(2, ReadILOperand(il, op4, addr), il.Const(1,16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16)),
+ il.LowPart(2, ReadILOperand(il, op4, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(2),
+ il.Add(8,
+ il.Or(8,
+ il.ShiftLeft(8,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op1, addr)
+ ),
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Register(8, LLIL_TEMP(2))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op2.reg,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(2)),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMMLA:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), il.ArithShiftRight(8, il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr)), il.Const(1, 32))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMMLAR:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Add(8, il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr)), il.Const(8, 0x80000000))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.ArithShiftRight(4,
+ il.Register(8, LLIL_TEMP(0)),
+ il.Const(1, 32)
+ ),
+ ReadILOperand(il, op4, addr)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMMLS:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr))));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(1), il.ShiftLeft(8, ReadILOperand(il, op4, addr), il.Const(1, 32))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.ArithShiftRight(4,
+ il.Sub(8,
+ il.Register(8, LLIL_TEMP(1)),
+ il.Register(8, LLIL_TEMP(0))
+ ),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMMLSR:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr))));
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(1), il.ShiftLeft(8, ReadILOperand(il, op4, addr), il.Const(1, 32))));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.ArithShiftRight(4,
+ il.Add(8,
+ il.Sub(8,
+ il.Register(8, LLIL_TEMP(1)),
+ il.Register(8, LLIL_TEMP(0))
+ ),
+ il.Const(8, 0x80000000)
+ ),
+ il.Const(1, 32)
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMUAD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMUADX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMMUL:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr))));
+ il.AddInstruction(il.SetRegister(4, op1.reg, il.ArithShiftRight(4, il.Register(8, LLIL_TEMP(0)), il.Const(1, 32))));
+ });
+ break;
+ case ARMV7_SMMULR:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(8, LLIL_TEMP(0), il.Add(8, il.Mult(8, ReadILOperand(il, op2, addr), ReadILOperand(il, op3, addr)), il.Const(4, 0x80000000))));
+ il.AddInstruction(il.SetRegister(4, op1.reg, il.ArithShiftRight(4, il.Register(8, LLIL_TEMP(0)), il.Const(1, 32))));
+ });
+ break;
+ case ARMV7_UMULL:
+ case ARMV7_SMULL:
+ /* op2:op1 = op3 * op4 */
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ ExprId product;
+ if (instr.operation == ARMV7_UMULL)
+ product = il.MultDoublePrecUnsigned(get_register_size(op3.reg), ReadILOperand(il, op3, addr), ReadILOperand(il, op4, addr));
+ else
+ product = il.MultDoublePrecSigned(get_register_size(op3.reg), ReadILOperand(il, op3, addr), ReadILOperand(il, op4, addr));
+
+ il.AddInstruction(
+ il.SetRegisterSplit(get_register_size(op1.reg),
+ op2.reg,
+ op1.reg,
+ product
+ )
+ );
+ });
+ break;
+ case ARMV7_SMULBB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ )
+ );
+ });
+ break;
+ case ARMV7_SMULBT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ )
+ );
+ });
+ break;
+ case ARMV7_SMULTB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ )
+ );
+ });
+ break;
+ case ARMV7_SMULTT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16))),
+ il.LowPart(2, il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16)))
+ )
+ )
+ );
+ });
+ break;
+ case ARMV7_SMULWB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ ReadILOperand(il, op2, addr),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMULWT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Mult(4,
+ ReadILOperand(il, op2, addr),
+ il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1,16))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMUSD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SMUSDX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Mult(4,
+ il.ArithShiftRight(4, ReadILOperand(il, op2, addr), il.Const(1, 16)),
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Mult(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ArithShiftRight(4, ReadILOperand(il, op3, addr), il.Const(1, 16))
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Sub(4,
+ il.Register(4, LLIL_TEMP(1)),
+ il.Register(4, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_SSAT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.ShiftLeft(4,
+ il.Const(1, 2),
+ ReadILOperand(il, op2, addr)
+ ),
+ il.Const(1,1)
+ )
+ ));
+
+ Saturate(il, op1.reg, ReadILOperand(il, op3, addr), il.Register(4, LLIL_TEMP(0)), true);
+ });
+ break;
+ case ARMV7_SSAT16:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Sub(2,
+ il.ShiftLeft(2,
+ il.Const(1, 2),
+ ReadILOperand(il, op2, addr)
+ ),
+ il.Const(1, 1)
+ )
+ ));
+
+ Saturate(il, LLIL_TEMP(1), il.LowPart(2, ReadILOperand(il, op3, addr)), il.Register(4, LLIL_TEMP(0)), true);
+ Saturate(il, LLIL_TEMP(2), il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1, 16)), il.Register(4, LLIL_TEMP(0)), true);
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ZeroExtend(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.ZeroExtend(2, il.Register(2, LLIL_TEMP(1)))
+ )
+ ));
+ });
+ break;
+ case ARMV7_STMDA:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ uint32_t lowestSetBit = 1337;
+ uint32_t numToLoad = 0;
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ numToLoad++;
+ if (j < lowestSetBit)
+ lowestSetBit = j;
+ }
+ }
+ //Set base address
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, (4*numToLoad) - 4)
+ )
+ ));
+ //Check only the first 15 bits, 16th bit is PC which is handled at the bottom
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ if (j == op1.reg && op1.flags.wb == 1 && j != lowestSetBit)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Unimplemented()
+ )
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(get_register_size((enum Register)j), j)
+ )
+ );
+ }
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 4)
+ )
+ ));
+ }
+ }
+ // Check if PC is stored
+ if (((op2.reg >> 15) & 1) == 1)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, REG_PC)
+ )
+ );
+ }
+ // Check for writeback
+ if (op1.flags.wb == 1)
+ {
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Sub(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, 4*numToLoad)
+ )
+ ));
+ }
+ });
+ break;
+ case ARMV7_STMDB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ uint32_t lowestSetBit = 1337;
+ uint32_t numToLoad = 0;
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ numToLoad++;
+ if (j < lowestSetBit)
+ lowestSetBit = j;
+ }
+ }
+ //Set base address
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, 4*numToLoad)
+ )
+ ));
+ //Check only the first 15 bits, 16th bit is PC which is handled at the bottom
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ if (j == op1.reg && op1.flags.wb == 1 && j != lowestSetBit)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Unimplemented()
+ )
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(get_register_size((enum Register)j), j)
+ )
+ );
+ }
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 4)
+ )
+ ));
+ }
+ }
+ // Check if PC is stored
+ if (((op2.reg >> 15) & 1) == 1)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, REG_PC)
+ )
+ );
+ }
+ // Check for writeback
+ if (op1.flags.wb == 1)
+ {
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Sub(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, 4*numToLoad)
+ )
+ ));
+ }
+ });
+ break;
+ case ARMV7_STMIB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ uint32_t lowestSetBit = 1337;
+ uint32_t numToLoad = 0;
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ numToLoad++;
+ if (j < lowestSetBit)
+ lowestSetBit = j;
+ }
+ }
+ //Set base address
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(1, 4)
+ )
+ ));
+ //Check only the first 15 bits, 16th bit is PC which is handled at the bottom
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ if (j == op1.reg && op1.flags.wb == 1 && j != lowestSetBit)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Unimplemented()
+ )
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(get_register_size((enum Register)j), j)
+ )
+ );
+ }
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 4)
+ )
+ ));
+ }
+ }
+ // Check if PC is stored
+ if (((op2.reg >> 15) & 1) == 1)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, REG_PC)
+ )
+ );
+ }
+ // Check for writeback
+ if (op1.flags.wb == 1)
+ {
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, 4*numToLoad)
+ )
+ ));
+ }
+ });
+ break;
+ case ARMV7_STM:
+ case ARMV7_STMIA:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ uint32_t lowestSetBit = 1337;
+ uint32_t numToLoad = 0;
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ numToLoad++;
+ if (j < lowestSetBit)
+ lowestSetBit = j;
+ }
+ }
+ //Set base address
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ ReadRegisterOrPointer(il, op1, addr)
+ ));
+ //Check only the first 15 bits, 16th bit is PC which is handled at the bottom
+ for (uint32_t j = 0; j < 15; j++)
+ {
+ if (((op2.reg >> j) & 1) == 1)
+ {
+ if (j == op1.reg && op1.flags.wb == 1 && j != lowestSetBit)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Unimplemented()
+ )
+ );
+ }
+ else
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(get_register_size((enum Register)j), j)
+ )
+ );
+ }
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 4)
+ )
+ ));
+ }
+ }
+ // Check if PC is stored
+ if (((op2.reg >> 15) & 1) == 1)
+ {
+ il.AddInstruction(
+ il.Store(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, REG_PC)
+ )
+ );
+ }
+ // Check for writeback
+ if (op1.flags.wb == 1)
+ {
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadRegisterOrPointer(il, op1, addr),
+ il.Const(4, 4*numToLoad)
+ )
+ ));
+ }
+ });
+ break;
+ case ARMV7_STREX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ StoreExclusive(il, 4, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_STREXH:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ StoreExclusive(il, 2, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_STREXB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ StoreExclusive(il, 1, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_STR:
+ case ARMV7_STRT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Store(il, 4, op1, op2, addr);
+ });
+ break;
+ case ARMV7_STRH:
+ case ARMV7_STRHT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Store(il, 2, op1, op2, addr);
+ });
+ break;
+ case ARMV7_STRB:
+ case ARMV7_STRBT:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Store(il, 1, op1, op2, addr);
+ });
+ break;
+ case ARMV7_STREXD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ StorePairExclusive(arch, il, op1, op2, op3, op4, addr);
+ });
+ break;
+ case ARMV7_STRD:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ StorePair(arch, il, op1, op2, op3, addr);
+ });
+ break;
+ case ARMV7_SUB:
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.Sub(get_register_size(op2.reg),
+ ReadRegisterOrPointer(il, op2, addr),
+ ReadILOperand(il, op3, addr), flagOperation[instr.setsFlags])));
+ break;
+ case ARMV7_SVC:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, FAKEREG_SYSCALL_INFO, il.Const(4, op1.imm)));
+ il.AddInstruction(il.SystemCall());
+ });
+ break;
+ case ARMV7_SWP:
+ if (op1.reg == op2.reg)
+ {
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Load(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op3, addr)
+ )
+ ));
+ il.AddInstruction(il.Store(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op3, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ ));
+ il.AddInstruction(SetRegisterOrBranch(il, op1.reg,
+ il.Register(4, LLIL_TEMP(0))
+ ));
+ });
+ }
+ else
+ {
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(SetRegisterOrBranch(il, op1.reg,
+ il.Load(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op3, addr)
+ )
+ ));
+ il.AddInstruction(il.Store(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op3, addr),
+ ReadRegisterOrPointer(il, op2, addr)
+ ));
+ });
+ }
+ break;
+ case ARMV7_SWPB:
+ if (op1.reg == op2.reg)
+ {
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(1, LLIL_TEMP(0),
+ il.Load(1,
+ ReadRegisterOrPointer(il, op3, addr)
+ )
+ ));
+ il.AddInstruction(il.Store(1,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.And(1,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 0xff)
+ )
+ ));
+ il.AddInstruction(SetRegisterOrBranch(il, op1.reg,
+ il.ZeroExtend(4, il.Register(1, LLIL_TEMP(0)))
+ ));
+ });
+ }
+ else
+ {
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(SetRegisterOrBranch(il, op1.reg,
+ il.ZeroExtend(4,
+ il.Load(1,
+ ReadRegisterOrPointer(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.Store(1,
+ ReadRegisterOrPointer(il, op3, addr),
+ il.And(1,
+ ReadRegisterOrPointer(il, op2, addr),
+ il.Const(1, 0xff)
+ )
+ ));
+ });
+ }
+ break;
+ case ARMV7_SXTAB:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ ReadILOperand(il, op3, addr)
+ ));
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadILOperand(il, op2, addr),
+ il.SignExtend(4,
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SXTAB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ ReadILOperand(il, op3, addr)
+ ));
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Add(2,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.SignExtend(2,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ )
+ )
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.Add(2,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.SignExtend(2,
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SXTAH:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadILOperand(il, op2, addr),
+ il.SignExtend(4,
+ il.LowPart(2, ReadILOperand(il, op3, addr))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SXTB:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.ArithShiftRight(get_register_size(op1.reg),
+ il.ShiftLeft(get_register_size(op1.reg), ReadRegisterOrPointer(il, op2, addr), il.Const(get_register_size(op1.reg), get_register_size(op1.reg)-8)),
+ il.Const(get_register_size(op1.reg), (get_register_size(op1.reg)*8)-8))));
+ break;
+ case ARMV7_SXTB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ ReadILOperand(il, op2, addr)
+ ));
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.SignExtend(2,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ )
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.SignExtend(2,
+ il.Register(1, LLIL_TEMP(0))
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_SXTH:
+ {
+ ExprId source = il.Register(4, op2.reg);
+
+ if (op2.shift == SHIFT_ROR && op2.imm)
+ source = il.RotateRight(4, source, il.Const(1, op2.imm));
+
+ ConditionExecute(il, instr.cond,
+ il.SetRegister(4,
+ op1.reg,
+ il.SignExtend(4,
+ il.LowPart(2,
+ source
+ )
+ )
+ )
+ );
+
+ break;
+ }
+
+ /*case ARMV7_SXTW:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.ArithShiftRight(get_register_size(op1.reg),
+ il.ShiftLeft(get_register_size(op1.reg), ReadRegisterOrPointer(il, op2, addr), il.Const(get_register_size(op1.reg), get_register_size(op1.reg)-16)),
+ il.Const(get_register_size(op1.reg), (get_register_size(op1.reg)*8)-16))));
+ break;
+ */
+ case ARMV7_TEQ:
+ ConditionExecute(il, instr.cond, il.Xor(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadILOperand(il, op2, addr), IL_FLAGWRITE_CNZ));
+ break;
+ case ARMV7_TST:
+ ConditionExecute(il, instr.cond, il.And(get_register_size(op1.reg),
+ ReadRegisterOrPointer(il, op1, addr),
+ ReadILOperand(il, op2, addr), IL_FLAGWRITE_ALL));
+ break;
+ case ARMV7_UBFX:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op1.reg),
+ il.LogicalShiftRight(get_register_size(op2.reg), ReadILOperand(il, op2, addr), il.Const(1, op3.imm)),
+ il.Const(get_register_size(op2.reg), BITMASK(op4.imm, 0)))));
+ break;
+ case ARMV7_USAD8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
+ il.Sub(4,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, i*8)
+ )
+ ),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadILOperand(il, op3, addr),
+ il.Const(1, i*8)
+ )
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
+ il.Sub(4,
+ il.Xor(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.Const(1, 31)
+ )
+ ),
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.Const(1, 31)
+ )
+ )
+ ));
+ }
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Add(4,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ ),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(2)),
+ il.Register(4, LLIL_TEMP(3))
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_USADA8:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ for (int i = 0; i < 4; i++)
+ {
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
+ il.Sub(4,
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, i*8)
+ )
+ ),
+ il.LowPart(1,
+ il.ArithShiftRight(4,
+ ReadILOperand(il, op3, addr),
+ il.Const(1, i*8)
+ )
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(i),
+ il.Sub(4,
+ il.Xor(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.Const(1, 31)
+ )
+ ),
+ il.ArithShiftRight(4,
+ il.Register(4, LLIL_TEMP(i)),
+ il.Const(1, 31)
+ )
+ )
+ ));
+ }
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.LowPart(4,
+ il.Add(4,
+ ReadILOperand(il, op4, addr),
+ il.Add(4,
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Register(4, LLIL_TEMP(1))
+ ),
+ il.Add(4,
+ il.Register(4, LLIL_TEMP(2)),
+ il.Register(4, LLIL_TEMP(3))
+ )
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_USAT:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Sub(4,
+ il.ShiftLeft(4,
+ il.Const(1, 1),
+ ReadILOperand(il, op2, addr)
+ ),
+ il.Const(1, 1)
+ )
+ ));
+
+ Saturate(il, op1.reg, ReadILOperand(il, op3, addr), il.Register(4, LLIL_TEMP(0)), false);
+
+ });
+ break;
+ case ARMV7_USAT16:
+ ConditionExecute(addr, instr.cond, instr, il, [&](size_t, Instruction&, LowLevelILFunction& il){
+ il.AddInstruction(il.SetRegister(2, LLIL_TEMP(0),
+ il.Sub(2,
+ il.ShiftLeft(2,
+ il.Const(1, 1),
+ ReadILOperand(il, op2, addr)
+ ),
+ il.Const(1, 1)
+ )
+ ));
+
+ Saturate(il, LLIL_TEMP(1), il.LowPart(2, ReadILOperand(il, op3, addr)), il.Register(4, LLIL_TEMP(0)), false);
+ Saturate(il, LLIL_TEMP(2), il.ArithShiftRight(2, ReadILOperand(il, op3, addr), il.Const(1, 16)), il.Register(4, LLIL_TEMP(0)), false);
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ZeroExtend(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(2)),
+ il.Const(1, 16)
+ )
+ ),
+ il.ZeroExtend(2, il.Register(2, LLIL_TEMP(1)))
+ )
+ ));
+ });
+ break;
+ case ARMV7_USAX:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0),
+ il.Add(4,
+ il.LowPart(2,
+ ReadILOperand(il, op2, addr)
+ ),
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op3, addr),
+ il.Const(1,16)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(1),
+ il.Sub(4,
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1,16)
+ ),
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ ));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Register(2, LLIL_TEMP(1)),
+ il.Const(1, 16)
+ ),
+ il.Register(2, LLIL_TEMP(0))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UXTAB:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.Add(get_register_size(op2.reg), ReadRegisterOrPointer(il, op2, addr),
+ il.And(get_register_size(op3.reg),
+ GetShiftedRegister(il, op3), il.Const(get_register_size(op3.reg), 0xff)))));
+ break;
+ case ARMV7_UXTAB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), ReadILOperand(il, op3, addr)));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.Add(4,
+ il.LowPart(2, ReadILOperand(il, op2, addr)),
+ il.ZeroExtend(2, il.Register(1, LLIL_TEMP(0)))
+ ),
+ il.Const(1, 32)
+ ),
+ il.Add(4,
+ il.LogicalShiftRight(2,
+ ReadILOperand(il, op2, addr),
+ il.Const(1, 16)
+ ),
+ il.ZeroExtend(2,
+ il.LowPart(1,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ )
+ )
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UXTAH:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Add(4,
+ ReadILOperand(il, op2, addr),
+ il.ZeroExtend(4,
+ il.LowPart(2,
+ ReadILOperand(il, op3, addr)
+ )
+ )
+ )
+ ));
+ });
+ break;
+ case ARMV7_UXTB:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op2.reg), GetShiftedRegister(il, op2), il.Const(get_register_size(op2.reg), 0xff))));
+ break;
+ case ARMV7_UXTB16:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+
+ il.AddInstruction(il.SetRegister(4, LLIL_TEMP(0), ReadILOperand(il, op2, addr)));
+ il.AddInstruction(il.SetRegister(4, op1.reg,
+ il.Or(4,
+ il.ShiftLeft(4,
+ il.ZeroExtend(2,
+ il.LowPart(1,
+ il.LogicalShiftRight(2,
+ il.Register(4, LLIL_TEMP(0)),
+ il.Const(1, 16)
+ )
+ )
+ ),
+ il.Const(1, 16)
+ ),
+ il.ZeroExtend(2, il.Register(1, LLIL_TEMP(0)))
+ )
+ ));
+ });
+ break;
+ case ARMV7_UXTH:
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.And(get_register_size(op2.reg), GetShiftedRegister(il, op2), il.Const(get_register_size(op2.reg), 0xffff))));
+ break;
+ case ARMV7_UDF:
+ il.AddInstruction(il.Trap(op1.imm));
+ break;
+ case ARMV7_UDIV:
+ if (op3.cls == NONE)
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.DivUnsigned(get_register_size(op1.reg), ReadRegisterOrPointer(il, op1, addr), ReadRegisterOrPointer(il, op2, addr))));
+ else
+ ConditionExecute(il, instr.cond, SetRegisterOrBranch(il, op1.reg,
+ il.DivUnsigned(get_register_size(op2.reg), ReadRegisterOrPointer(il, op2, addr), ReadRegisterOrPointer(il, op3, addr))));
+ break;
+ case ARMV7_VADD:
+ if((instr.dataType != DT_F32) && (instr.dataType != DT_F32) && (instr.dataType != DT_F64))
+ break;
+
+ ConditionExecute(il, instr.cond,
+ il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.FloatAdd(get_register_size(op1.reg),
+ il.Register(get_register_size(op2.reg), op2.reg),
+ il.Register(get_register_size(op3.reg), op3.reg)
+ )
+ )
+ );
+ break;
+ case ARMV7_VDIV:
+ if((instr.dataType != DT_F32) && (instr.dataType != DT_F32) && (instr.dataType != DT_F64))
+ break;
+
+ ConditionExecute(il, instr.cond,
+ il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.FloatDiv(get_register_size(op1.reg),
+ il.Register(get_register_size(op2.reg), op2.reg),
+ il.Register(get_register_size(op3.reg), op3.reg)
+ )
+ )
+ );
+ break;
+ case ARMV7_VLDR:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Load(il, false, get_register_size(op1.reg), op1, op2, addr);
+ });
+ break;
+ case ARMV7_VMOV:
+ /* VMOV(register) */
+ if (op1.cls == REG && op2.cls == REG && op3.cls == NONE)
+ {
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ ReadILOperand(il, op2, addr), flagOperation[instr.setsFlags]));
+ } else if (op1.cls == REG && (op2.cls == IMM || op2.cls == IMM64) && op3.cls == NONE) {
+ /* VMOV(immediate) */
+ if (get_register_size(op1.reg) == 16)
+ {
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.Or(16, il.Const(8, op2.imm64), il.ShiftLeft(16, il.Const(8, op2.imm64), il.Const(8, 64))),
+ flagOperation[instr.setsFlags]));
+ } else
+ {
+ ConditionExecute(il, instr.cond,
+ SetRegisterOrBranch(il, op1.reg,
+ il.Const(get_register_size(op1.reg), op2.imm64), flagOperation[instr.setsFlags]));
+ }
+ } else
+ {
+ ConditionExecute(il, instr.cond, il.Unimplemented());
+ }
+ break;
+ case ARMV7_VMUL:
+ if((instr.dataType != DT_F32) && (instr.dataType != DT_F32) && (instr.dataType != DT_F64))
+ break;
+
+ ConditionExecute(il, instr.cond,
+ il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.FloatMult(get_register_size(op1.reg),
+ il.Register(get_register_size(op2.reg), op2.reg),
+ il.Register(get_register_size(op3.reg), op3.reg)
+ )
+ )
+ );
+ break;
+ case ARMV7_VSTR:
+ ConditionExecute(addrSize, instr.cond, instr, il,
+ [&](size_t addrSize, Instruction& instr, LowLevelILFunction& il)
+ {
+ (void) addrSize;
+ (void) instr;
+ Store(il, get_register_size(op1.reg), op1, op2, addr);
+ });
+ break;
+ case ARMV7_VSUB:
+ if((instr.dataType != DT_F32) && (instr.dataType != DT_F32) && (instr.dataType != DT_F64))
+ break;
+
+ ConditionExecute(il, instr.cond,
+ il.SetRegister(get_register_size(op1.reg), op1.reg,
+ il.FloatSub(get_register_size(op1.reg),
+ il.Register(get_register_size(op2.reg), op2.reg),
+ il.Register(get_register_size(op3.reg), op3.reg)
+ )
+ )
+ );
+ break;
+ default:
+ //printf("Instruction: %s\n", get_operation(instr.operation));
+ ConditionExecute(il, instr.cond, il.Unimplemented());
+ break;
+ }
+ return true;
+}