Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions arch/arm64/arch_arm64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1043,6 +1043,38 @@ class Arm64Architecture : public Architecture
return "__tlbi";
case ARM64_INTRIN_AT:
return "__at";
case ARM64_INTRIN_ADDG:
return "__addg";
case ARM64_INTRIN_CMPP:
return "__cmpp";
case ARM64_INTRIN_GMI:
return "__gmi";
case ARM64_INTRIN_IRG:
return "__irg";
case ARM64_INTRIN_LDG:
return "__ldg";
case ARM64_INTRIN_LDGM:
return "__ldgm";
case ARM64_INTRIN_ST2G:
return "__st2g";
case ARM64_INTRIN_STG:
return "__stg";
case ARM64_INTRIN_STGM:
return "__stgm";
case ARM64_INTRIN_STGP:
return "__stgp";
case ARM64_INTRIN_STZ2G:
return "__stz2g";
case ARM64_INTRIN_STZG:
return "__stzg";
case ARM64_INTRIN_STZGM:
return "__stzgm";
case ARM64_INTRIN_SUBG:
return "__subg";
case ARM64_INTRIN_SUBP:
return "__subp";
case ARM64_INTRIN_SUBPS:
return "__subps";
default:
break;
}
Expand Down
157 changes: 157 additions & 0 deletions arch/arm64/il.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,10 @@ bool GetLowLevelILForInstruction(
ILSETREG_O(operand1, il.Add(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand1)), SETFLAGS)));
break;
case ARM64_ADDG:
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_ADDG,
{ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand3)), il.Const(1, IMM_O(operand4))}));
break;
case ARM64_ADC:
case ARM64_ADCS:
il.AddInstruction(ILSETREG_O(operand1,
Expand Down Expand Up @@ -1669,6 +1673,12 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.Sub(REGSZ_O(operand1), ILREG_O(operand1),
ReadILOperand(il, operand2, REGSZ_O(operand1)), SETFLAGS));
break;
case ARM64_CMPP:
il.AddInstruction(il.Intrinsic(
{RegisterOrFlag::Flag(IL_FLAG_N), RegisterOrFlag::Flag(IL_FLAG_Z), RegisterOrFlag::Flag(IL_FLAG_C),
RegisterOrFlag::Flag(IL_FLAG_V)},
ARM64_INTRIN_CMPP, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
case ARM64_CCMP:
{
LowLevelILLabel trueCode, falseCode, done;
Expand Down Expand Up @@ -2207,6 +2217,17 @@ bool GetLowLevelILForInstruction(
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_ERET, {}));
il.AddInstruction(il.Trap(0));
return false;
case ARM64_GMI:
il.AddInstruction(il.Intrinsic(
{RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_GMI, {ILREG_O(operand2), ILREG_O(operand3)}));
break;
case ARM64_IRG:
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_IRG,
{
ILREG_O(operand2),
operand3.operandClass == NONE ? il.Const(REGSZ_O(operand2), 0) : ILREG_O(operand3),
}));
break;
case ARM64_ISB:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_ISB, {}));
break;
Expand Down Expand Up @@ -2251,6 +2272,14 @@ bool GetLowLevelILForInstruction(
if (SetPacAttr)
ApplyAttributeToLastInstruction(il, SrcInstructionUsesPointerAuth);
break;
case ARM64_LDG:
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_LDG,
{GetILOperandEffectiveAddress(il, operand2, 8, operand2.operandClass, 0)}));
break;
case ARM64_LDGM:
il.AddInstruction(
il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_LDGM, {ILREG_O(operand2)}));
break;
case ARM64_LDRB:
case ARM64_LDURB:
LoadStoreOperandSize(il, true, false, 1, instr.operands[0], instr.operands[1]);
Expand Down Expand Up @@ -3406,6 +3435,120 @@ bool GetLowLevelILForInstruction(
case ARM64_STNP:
LoadStoreOperandPair(il, false, instr.operands[0], instr.operands[1], instr.operands[2]);
break;
case ARM64_ST2G:
switch (operand2.operandClass)
{
case MEM_POST_IDX:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_ST2G, {ILREG_O(operand1), ILREG_O(operand2)}));
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
break;
case MEM_PRE_IDX:
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_ST2G, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
default:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_ST2G,
{ILREG_O(operand1), GetILOperandEffectiveAddress(il, operand2, 8, operand2.operandClass, 0)}));
break;
}
break;
case ARM64_STG:
switch (operand2.operandClass)
{
case MEM_POST_IDX:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STG, {ILREG_O(operand1), ILREG_O(operand2)}));
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
break;
case MEM_PRE_IDX:
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STG, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
default:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STG,
{ILREG_O(operand1), GetILOperandEffectiveAddress(il, operand2, 8, operand2.operandClass, 0)}));
break;
}
break;
case ARM64_STGM:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STGM, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
case ARM64_STGP:
switch (operand3.operandClass)
{
case MEM_POST_IDX:
il.AddInstruction(
il.Intrinsic({}, ARM64_INTRIN_STGP, {ILREG_O(operand1), ILREG_O(operand2), ILREG_O(operand3)}));
if (IMM_O(operand3) != 0)
il.AddInstruction(ILSETREG_O(operand3,
il.Add(REGSZ_O(operand3), ILREG_O(operand3), il.Const(REGSZ_O(operand3), IMM_O(operand3)))));
break;
case MEM_PRE_IDX:
if (IMM_O(operand3) != 0)
il.AddInstruction(ILSETREG_O(operand3,
il.Add(REGSZ_O(operand3), ILREG_O(operand3), il.Const(REGSZ_O(operand3), IMM_O(operand3)))));
il.AddInstruction(
il.Intrinsic({}, ARM64_INTRIN_STGP, {ILREG_O(operand1), ILREG_O(operand2), ILREG_O(operand3)}));
break;
default:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STGP,
{ILREG_O(operand1), ILREG_O(operand2),
GetILOperandEffectiveAddress(il, operand3, 8, operand3.operandClass, 0)}));
break;
}
break;
case ARM64_STZ2G:
switch (operand2.operandClass)
{
case MEM_POST_IDX:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZ2G, {ILREG_O(operand1), ILREG_O(operand2)}));
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
break;
case MEM_PRE_IDX:
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZ2G, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
default:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZ2G,
{ILREG_O(operand1), GetILOperandEffectiveAddress(il, operand2, 8, operand2.operandClass, 0)}));
break;
}
break;
case ARM64_STZG:
switch (operand2.operandClass)
{
case MEM_POST_IDX:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZG, {ILREG_O(operand1), ILREG_O(operand2)}));
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
break;
case MEM_PRE_IDX:
if (IMM_O(operand2) != 0)
il.AddInstruction(ILSETREG_O(operand2,
il.Add(REGSZ_O(operand2), ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand2)))));
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZG, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
default:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZG,
{ILREG_O(operand1), GetILOperandEffectiveAddress(il, operand2, 8, operand2.operandClass, 0)}));
break;
}
break;
case ARM64_STZGM:
il.AddInstruction(il.Intrinsic({}, ARM64_INTRIN_STZGM, {ILREG_O(operand1), ILREG_O(operand2)}));
break;
case ARM64_STR:
switch (instr.encoding)
{
Expand Down Expand Up @@ -3450,6 +3593,20 @@ bool GetLowLevelILForInstruction(
operand1, il.Sub(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, instr.operands[2], REGSZ_O(operand1)), SETFLAGS)));
break;
case ARM64_SUBG:
il.AddInstruction(il.Intrinsic({RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_SUBG,
{ILREG_O(operand2), il.Const(REGSZ_O(operand2), IMM_O(operand3)), il.Const(1, IMM_O(operand4))}));
break;
case ARM64_SUBP:
il.AddInstruction(il.Intrinsic(
{RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_SUBP, {ILREG_O(operand2), ILREG_O(operand3)}));
break;
case ARM64_SUBPS:
il.AddInstruction(il.Intrinsic(
{RegisterOrFlag::Register(REG_O(operand1)), RegisterOrFlag::Flag(IL_FLAG_N),
RegisterOrFlag::Flag(IL_FLAG_Z), RegisterOrFlag::Flag(IL_FLAG_C), RegisterOrFlag::Flag(IL_FLAG_V)},
ARM64_INTRIN_SUBPS, {ILREG_O(operand2), ILREG_O(operand3)}));
break;
case ARM64_SVC:
case ARM64_HVC:
case ARM64_SMC:
Expand Down
16 changes: 16 additions & 0 deletions arch/arm64/il.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ enum Arm64Intrinsic : uint32_t
ARM64_INTRIN_TLBI,
ARM64_INTRIN_TLBI_REG,
ARM64_INTRIN_AT,
ARM64_INTRIN_ADDG,
ARM64_INTRIN_CMPP,
ARM64_INTRIN_GMI,
ARM64_INTRIN_IRG,
ARM64_INTRIN_LDG,
ARM64_INTRIN_LDGM,
ARM64_INTRIN_ST2G,
ARM64_INTRIN_STG,
ARM64_INTRIN_STGM,
ARM64_INTRIN_STGP,
ARM64_INTRIN_STZ2G,
ARM64_INTRIN_STZG,
ARM64_INTRIN_STZGM,
ARM64_INTRIN_SUBG,
ARM64_INTRIN_SUBP,
ARM64_INTRIN_SUBPS,
ARM64_INTRIN_NORMAL_END, /* needed so intrinsics can be extended by other lists, like neon
intrinsics */
ARM64_INTRIN_INVALID = 0xFFFFFFFF,
Expand Down