Skip to content
Open
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
36 changes: 36 additions & 0 deletions arch/arm64/arm64test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12846,6 +12846,41 @@
(b'\x20\xb8\xe0\x4e', 'LLIL_UNIMPL()'),
]

# FEAT_CPA (Checked Pointer Arithmetic). The pointer check these perform only rewrites bits 63:54 of
# the result, and only when the arithmetic escapes the address bits with SCTLR2_ELx.CPTA/CPTM
# enabled, so we lift the integer forms as plain arithmetic -- as we do for PAC above. The SVE forms
# are unlifted, like every other SVE encoding.
tests_cpa = [
# addpt x8, x27, x21, lsl #4 ADDPT_64_addsub_pt
(b'\x68\x33\x15\x9a',
'LLIL_SET_REG.q(x8,LLIL_ADD.q(LLIL_REG.q(x27),LLIL_LSL.q(LLIL_REG.q(x21),LLIL_CONST.b(0x4))))'),
# addpt x8, x27, x21 ADDPT_64_addsub_pt
(b'\x68\x23\x15\x9a', 'LLIL_SET_REG.q(x8,LLIL_ADD.q(LLIL_REG.q(x27),LLIL_REG.q(x21)))'),
# addpt x8, sp, x5 (Rn==31 is SP, not XZR) ADDPT_64_addsub_pt
(b'\xe8\x23\x05\x9a', 'LLIL_SET_REG.q(x8,LLIL_ADD.q(LLIL_REG.q(sp),LLIL_REG.q(x5)))'),
# addpt x1, x2, xzr (Rm==31 is XZR, not SP) ADDPT_64_addsub_pt
(b'\x41\x20\x1f\x9a', 'LLIL_SET_REG.q(x1,LLIL_ADD.q(LLIL_REG.q(x2),LLIL_CONST.q(0x0)))'),
# subpt x17, x13, x3, lsl #7 SUBPT_64_addsub_pt
(b'\xb1\x3d\x03\xda',
'LLIL_SET_REG.q(x17,LLIL_SUB.q(LLIL_REG.q(x13),LLIL_LSL.q(LLIL_REG.q(x3),LLIL_CONST.b(0x7))))'),
# subpt sp, sp, x5 SUBPT_64_addsub_pt
(b'\xff\x23\x05\xda', 'LLIL_SET_REG.q(sp,LLIL_SUB.q(LLIL_REG.q(sp),LLIL_REG.q(x5)))'),
# maddpt x3, x2, x1, x4 MADDPT_64A_dp_3src
(b'\x43\x10\x61\x9b',
'LLIL_SET_REG.q(x3,LLIL_ADD.q(LLIL_REG.q(x4),LLIL_MUL.q(LLIL_REG.q(x2),LLIL_REG.q(x1))))'),
# msubpt x3, x2, x1, x4 MSUBPT_64A_dp_3src
(b'\x43\x90\x61\x9b',
'LLIL_SET_REG.q(x3,LLIL_SUB.q(LLIL_REG.q(x4),LLIL_MUL.q(LLIL_REG.q(x2),LLIL_REG.q(x1))))'),
# addpt z3.d, z2.d, z1.d addpt_z_zz_
(b'\x43\x08\xe1\x04', 'LLIL_UNIMPL()'),
# subpt z3.d, p1/m, z3.d, z2.d subpt_z_p_zz_
(b'\x43\x04\xc5\x04', 'LLIL_UNIMPL()'),
# madpt z3.d, z2.d, z4.d madpt_z_zzz_
(b'\x83\xd8\xc2\x44', 'LLIL_UNIMPL()'),
# mlapt z3.d, z2.d, z1.d mlapt_z_zzz_
(b'\x43\xd0\xc1\x44', 'LLIL_UNIMPL()'),
]

# Apple's vendor-specific instructions, which occupy encoding space that ARM leaves unallocated.
# See arch/arm64/apple_vendor.cpp.
tests_apple_vendor = [
Expand Down Expand Up @@ -12981,6 +13016,7 @@

test_cases = \
tests_apple_vendor + \
tests_cpa + \
tests_cssc + \
tests_shll + \
tests_udf + \
Expand Down
56 changes: 56 additions & 0 deletions arch/arm64/disassembler/decode_scratchpad.c
Original file line number Diff line number Diff line change
Expand Up @@ -1536,6 +1536,16 @@ static unsigned rhsdr_0123x_reg(int v)

#define LAST_OPERAND_LSL_12 LAST_OPERAND_SHIFT(ShiftType_LSL, 12)

#define OPTIONAL_LSL_AMOUNT(AMOUNT) \
if (AMOUNT) \
{ \
LAST_OPERAND_SHIFT(ShiftType_LSL, AMOUNT); \
} \
else \
{ \
instr->operands[i - 1].shiftValueUsed = 0; \
}

#define ADD_OPERAND_OPTIONAL_PATTERN_MUL \
{ \
bool print_mul = ctx->imm != 1; \
Expand Down Expand Up @@ -5731,6 +5741,7 @@ int decode_scratchpad(context* ctx, Instruction* instr)
case ENC_MADD_64A_DP_3SRC:
case ENC_MSUB_64A_DP_3SRC:
case ENC_MADDPT_64A_DP_3SRC:
case ENC_MSUBPT_64A_DP_3SRC:
{
// <Xd>,<Xn>,<Xm>,<Xa>
ADD_OPERAND_XD;
Expand Down Expand Up @@ -6035,6 +6046,16 @@ int decode_scratchpad(context* ctx, Instruction* instr)
OPTIONAL_EXTEND_AMOUNT_64_BEHAVIOR1;
break;
}
case ENC_ADDPT_64_ADDSUB_PT:
case ENC_SUBPT_64_ADDSUB_PT:
{
// <Xd|SP>,<Xn|SP>,<Xm>{, LSL #<amount>}
ADD_OPERAND_XD_SP;
ADD_OPERAND_XN_SP;
ADD_OPERAND_XM;
OPTIONAL_LSL_AMOUNT(ctx->shift);
break;
}
case ENC_IRG_64I_DP_2SRC:
{
// <Xd|SP>,<Xn|SP>{,<Xm>}
Expand Down Expand Up @@ -6842,6 +6863,31 @@ int decode_scratchpad(context* ctx, Instruction* instr)
ADD_OPERAND_CONST;
break;
}
case ENC_ADDPT_Z_ZZ_:
case ENC_SUBPT_Z_ZZ_:
{
// <Zd>.D,<Zn>.D,<Zm>.D
ADD_OPERAND_ZREG_T(ctx->d, _1D)
ADD_OPERAND_ZREG_T(ctx->n, _1D)
ADD_OPERAND_ZREG_T(ctx->m, _1D)
break;
}
case ENC_MLAPT_Z_ZZZ_:
{
// <Zda>.D,<Zn>.D,<Zm>.D
ADD_OPERAND_ZREG_T(ctx->da, _1D)
ADD_OPERAND_ZREG_T(ctx->n, _1D)
ADD_OPERAND_ZREG_T(ctx->m, _1D)
break;
}
case ENC_MADPT_Z_ZZZ_:
{
// <Zdn>.D,<Zm>.D,<Za>.D
ADD_OPERAND_ZREG_T(ctx->dn, _1D)
ADD_OPERAND_ZREG_T(ctx->m, _1D)
ADD_OPERAND_ZREG_T(ctx->a, _1D)
break;
}
case ENC_ADD_Z_ZZ_:
case ENC_FADD_Z_ZZ_:
case ENC_FMUL_Z_ZZ_:
Expand Down Expand Up @@ -7303,6 +7349,16 @@ int decode_scratchpad(context* ctx, Instruction* instr)
ADD_OPERAND_CONST;
break;
}
case ENC_ADDPT_Z_P_ZZ_:
case ENC_SUBPT_Z_P_ZZ_:
{
// <Zdn>.D,<Pg>/M,<Zdn>.D,<Zm>.D
ADD_OPERAND_ZREG_T(ctx->dn, _1D)
ADD_OPERAND_PRED_REG_QUAL(ctx->g, 'm');
ADD_OPERAND_ZREG_T(ctx->dn, _1D)
ADD_OPERAND_ZREG_T(ctx->m, _1D)
break;
}
case ENC_ADD_Z_P_ZZ_:
case ENC_AND_Z_P_ZZ_:
case ENC_ASR_Z_P_ZZ_:
Expand Down
32 changes: 32 additions & 0 deletions arch/arm64/il.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1378,6 +1378,21 @@ bool GetLowLevelILForInstruction(
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_ADDPT:
switch (instr.encoding)
{
case ENC_ADDPT_Z_P_ZZ_:
case ENC_ADDPT_Z_ZZ_:
if (!preferIntrinsics())
il.AddInstruction(il.Unimplemented());
return true;
default: break;
}
// FEAT_CPA checked pointer addition, lifted as if checking is disabled
il.AddInstruction(ILSETREG_O(operand1,
il.Add(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand1)))));
break;
case ARM64_ADC:
case ARM64_ADCS:
il.AddInstruction(ILSETREG_O(operand1,
Expand Down Expand Up @@ -2927,6 +2942,7 @@ bool GetLowLevelILForInstruction(
}
break;
case ARM64_MADD:
case ARM64_MADDPT: // FEAT_CPA checked multiply-add, lifted as if checking is disabled
il.AddInstruction(ILSETREG_O(operand1,
ILADDREG_O(operand4, il.Mult(REGSZ_O(operand1), ILREG_O(operand2), ILREG_O(operand3)))));
break;
Expand All @@ -2953,6 +2969,7 @@ bool GetLowLevelILForInstruction(
break;
}
case ARM64_MSUB:
case ARM64_MSUBPT: // FEAT_CPA checked multiply-subtract, lifted as if checking is disabled
il.AddInstruction(ILSETREG_O(
operand1, il.Sub(REGSZ_O(operand1), ILREG_O(operand4),
il.Mult(REGSZ_O(operand1), ILREG_O(operand2), ILREG_O(operand3)))));
Expand Down Expand Up @@ -3755,6 +3772,21 @@ bool GetLowLevelILForInstruction(
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_SUBPT:
switch (instr.encoding)
{
case ENC_SUBPT_Z_P_ZZ_:
case ENC_SUBPT_Z_ZZ_:
if (!preferIntrinsics())
il.AddInstruction(il.Unimplemented());
return true;
default: break;
}
// FEAT_CPA checked pointer subtraction, lifted as if checking is disabled
il.AddInstruction(ILSETREG_O(operand1,
il.Sub(REGSZ_O(operand1), ILREG_O(operand2),
ReadILOperand(il, operand3, REGSZ_O(operand1)))));
break;
case ARM64_SUBP:
il.AddInstruction(il.Intrinsic(
{RegisterOrFlag::Register(REG_O(operand1))}, ARM64_INTRIN_SUBP, {ILREG_O(operand2), ILREG_O(operand3)}));
Expand Down