summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Rowe <mark@vector35.com>2025-10-18 09:15:19 -0700
committerMark Rowe <mark@vector35.com>2025-10-20 08:41:27 -0700
commit432984039635733d2a5bf7b561e17014a6b93084 (patch)
tree32e34c51295a68012a96da1b624316d041e748f6
parent1ec0d4fced11af730db0d9273fb512563fc02a0a (diff)
[AArch64] Lift MTE instructions to intrinsics
-rw-r--r--arch/arm64/arch_arm64.cpp32
-rw-r--r--arch/arm64/il.cpp157
-rw-r--r--arch/arm64/il.h16
3 files changed, 205 insertions, 0 deletions
diff --git a/arch/arm64/arch_arm64.cpp b/arch/arm64/arch_arm64.cpp
index 2ec4a9f2..7d67854f 100644
--- a/arch/arm64/arch_arm64.cpp
+++ b/arch/arm64/arch_arm64.cpp
@@ -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;
}
diff --git a/arch/arm64/il.cpp b/arch/arm64/il.cpp
index 348bae73..cbda172a 100644
--- a/arch/arm64/il.cpp
+++ b/arch/arm64/il.cpp
@@ -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,
@@ -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;
@@ -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;
@@ -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]);
@@ -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)
{
@@ -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:
diff --git a/arch/arm64/il.h b/arch/arm64/il.h
index 37192275..9b442301 100644
--- a/arch/arm64/il.h
+++ b/arch/arm64/il.h
@@ -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,