summaryrefslogtreecommitdiff
path: root/arch/arm64/il.cpp
diff options
context:
space:
mode:
authorJosh Ferrell <josh@vector35.com>2024-06-11 10:16:39 -0400
committerJosh Ferrell <josh@vector35.com>2024-06-11 10:20:05 -0400
commit7688bfb90a9493716f662b37d0d3c761d2a811f0 (patch)
tree24addb49e900423fd867de20bf85ad5dabff1226 /arch/arm64/il.cpp
parent52e930719e0d9ad67ff5978a6830fe2c60a9cd58 (diff)
Fix lifting of pair load operations when first and third operand are equal and reduce code duplication
Diffstat (limited to 'arch/arm64/il.cpp')
-rw-r--r--arch/arm64/il.cpp60
1 files changed, 25 insertions, 35 deletions
diff --git a/arch/arm64/il.cpp b/arch/arm64/il.cpp
index ff1f5488..8af45d87 100644
--- a/arch/arm64/il.cpp
+++ b/arch/arm64/il.cpp
@@ -679,39 +679,6 @@ static int consolidate_vector(
return 1;
}
-static void LoadStoreOperandPair(LowLevelILFunction& il, bool load, InstructionOperand& operand1,
- InstructionOperand& operand2, InstructionOperand& operand3)
-{
- unsigned sz = REGSZ_O(operand1);
-
- /* do pre-indexing */
- ExprId tmp = GetILOperandPreIndex(il, operand3);
- if (tmp)
- il.AddInstruction(tmp);
-
- /* compute addresses */
- OperandClass oclass = (operand3.operandClass == MEM_PRE_IDX) ? MEM_REG : operand3.operandClass;
- ExprId addr0 = GetILOperandEffectiveAddress(il, operand3, 8, oclass, 0);
- ExprId addr1 = GetILOperandEffectiveAddress(il, operand3, 8, oclass, sz);
-
- /* load/store */
- if (load)
- {
- il.AddInstruction(ILSETREG_O(operand1, il.Load(sz, addr0)));
- il.AddInstruction(ILSETREG_O(operand2, il.Load(sz, addr1)));
- }
- else
- {
- il.AddInstruction(il.Store(sz, addr0, ILREG_O(operand1)));
- il.AddInstruction(il.Store(sz, addr1, ILREG_O(operand2)));
- }
-
- /* do post-indexing */
- tmp = GetILOperandPostIndex(il, operand3);
- if (tmp)
- il.AddInstruction(tmp);
-}
-
static void LoadStoreOperandPairSize(LowLevelILFunction& il, bool load, size_t load_size, InstructionOperand& operand1,
InstructionOperand& operand2, InstructionOperand& operand3)
{
@@ -728,8 +695,23 @@ static void LoadStoreOperandPairSize(LowLevelILFunction& il, bool load, size_t l
/* load/store */
if (load)
{
- il.AddInstruction(ILSETREG_O(operand1, il.Load(load_size, addr0)));
- il.AddInstruction(ILSETREG_O(operand2, il.Load(load_size, addr1)));
+ // We lift this instruction differently if operand1 and operand3 are equal as to not break outlining in the common case,
+ // since outlining does not seem to handle intermediate stores to temporary registers
+ // TODO: unify lifting once outlining handles intermediate temporary stores
+ if (REG_O(operand1) != REG_O(operand3))
+ {
+ // {op} X, Y, [Z]
+ il.AddInstruction(ILSETREG_O(operand1, il.Load(load_size, addr0)));
+ il.AddInstruction(ILSETREG_O(operand2, il.Load(load_size, addr1)));
+ }
+ else
+ {
+ // {op} X, Y, [X]
+ // Prevent clobbering of source during write to operand1 by storing source in a temporary register
+ il.AddInstruction(il.SetRegister(REGSZ_O(operand1), LLIL_TEMP(0), addr1));
+ il.AddInstruction(ILSETREG_O(operand1, il.Load(load_size, addr0)));
+ il.AddInstruction(ILSETREG_O(operand2, il.Load(load_size, il.Register(load_size, LLIL_TEMP(0)))));
+ }
}
else
{
@@ -744,6 +726,14 @@ static void LoadStoreOperandPairSize(LowLevelILFunction& il, bool load, size_t l
}
+static void LoadStoreOperandPair(LowLevelILFunction& il, bool load, InstructionOperand& operand1,
+ InstructionOperand& operand2, InstructionOperand& operand3)
+{
+ unsigned sz = REGSZ_O(operand1);
+ LoadStoreOperandPairSize(il, load, sz, operand1, operand2, operand3);
+}
+
+
static void LoadStoreVector(
LowLevelILFunction& il, bool is_load, InstructionOperand& oper0, InstructionOperand& oper1)
{